Java/Swing Components/GlassPane

Материал из Java эксперт
Перейти к: навигация, поиск

Add Image To GlassPane

   <source lang="java">

/*

* Copyright (c) 2007, Romain Guy
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
*   * Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*   * Redistributions in binary form must reproduce the above
*     copyright notice, this list of conditions and the following
*     disclaimer in the documentation and/or other materials provided
*     with the distribution.
*   * Neither the name of the TimingFramework project nor the names of its
*     contributors may be used to endorse or promote products derived
*     from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

import java.awt.AWTEvent; import java.awt.Cursor; import java.awt.Graphics; import java.awt.Window; import java.awt.event.MouseEvent; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.Arrays; import javax.imageio.ImageIO; import javax.swing.JComponent; import javax.swing.SwingUtilities; /**

*
* @author Romain Guy
*/

public class GlassMouseCursor extends javax.swing.JFrame {

   public GlassMouseCursor() {
       initComponents();
       setGlassPane(new WatermarkGlassPane());
       getGlassPane().setVisible(true);
   }
   
   /** This method is called from within the constructor to
    * initialize the form.
    * WARNING: Do NOT modify this code. The content of this method is
    * always regenerated by the Form Editor.
    */
   // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
   private void initComponents() {
       javax.swing.JLabel jLabel1;
       javax.swing.JLabel jLabel2;
       javax.swing.JLabel jLabel3;
       javax.swing.JLabel jLabel4;
       javax.swing.JLabel jLabel5;
       javax.swing.JList jList1;
       javax.swing.JScrollPane jScrollPane1;
       javax.swing.JScrollPane jScrollPane2;
       javax.swing.JTextArea jTextArea1;
       javax.swing.JTextField jTextField1;
       javax.swing.JTextField jTextField2;
       javax.swing.JTextField jTextField3;
       javax.swing.JTextField jTextField4;
       jScrollPane1 = new javax.swing.JScrollPane();
       jList1 = new javax.swing.JList();
       jLabel1 = new javax.swing.JLabel();
       jLabel2 = new javax.swing.JLabel();
       jLabel3 = new javax.swing.JLabel();
       jLabel4 = new javax.swing.JLabel();
       jLabel5 = new javax.swing.JLabel();
       jTextField1 = new javax.swing.JTextField();
       jTextField2 = new javax.swing.JTextField();
       jTextField3 = new javax.swing.JTextField();
       jTextField4 = new javax.swing.JTextField();
       jScrollPane2 = new javax.swing.JScrollPane();
       jTextArea1 = new javax.swing.JTextArea();
       setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
       setTitle("Glass Pane and Mouse Cursor");
       jList1.setModel(new javax.swing.AbstractListModel() {
           String[] strings = { "Jean-Baptiste Freymann", "Nicolas Igot", "Matthieu Grandvallet", "Fr\u00e9d\u00e9ric Hofmann" };
           public int getSize() { return strings.length; }
           public Object getElementAt(int i) { return strings[i]; }
       });
       jList1.setSelectedIndex(0);
       jScrollPane1.setViewportView(jList1);
       jLabel1.setText("First Name");
       jLabel2.setText("Last Name");
       jLabel3.setText("Phone");
       jLabel4.setText("Email");
       jLabel5.setText("Address");
       jTextField1.setText("Jean-Baptiste");
       jTextField2.setText("Freymann");
       jTextField3.setText("(555) 462-1492");
       jTextField4.setText("roukin@acme.ru");
       jTextArea1.setColumns(15);
       jTextArea1.setRows(5);
       jTextArea1.setText("462 Park View Drive\n54999 Santa Clara, CA\nUSA");
       jScrollPane2.setViewportView(jTextArea1);
       org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane());
       getContentPane().setLayout(layout);
       layout.setHorizontalGroup(
           layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
           .add(layout.createSequentialGroup()
               .addContainerGap()
               .add(jScrollPane1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 152, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
               .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
               .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                   .add(org.jdesktop.layout.GroupLayout.TRAILING, jLabel5)
                   .add(org.jdesktop.layout.GroupLayout.TRAILING, jLabel4)
                   .add(org.jdesktop.layout.GroupLayout.TRAILING, jLabel3)
                   .add(org.jdesktop.layout.GroupLayout.TRAILING, jLabel2)
                   .add(org.jdesktop.layout.GroupLayout.TRAILING, jLabel1))
               .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
               .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING, false)
                   .add(jTextField1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                   .add(jTextField2, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                   .add(jTextField3, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                   .add(jTextField4, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                   .add(jScrollPane2, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 209, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
               .addContainerGap())
       );
       layout.linkSize(new java.awt.ruponent[] {jScrollPane2, jTextField1, jTextField2, jTextField3, jTextField4}, org.jdesktop.layout.GroupLayout.HORIZONTAL);
       layout.setVerticalGroup(
           layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
           .add(layout.createSequentialGroup()
               .addContainerGap()
               .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                   .add(layout.createSequentialGroup()
                       .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                           .add(jLabel1)
                           .add(jTextField1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                       .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                       .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                           .add(jLabel2)
                           .add(jTextField2, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                       .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                       .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                           .add(jLabel3)
                           .add(jTextField3, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                       .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                       .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                           .add(jLabel4)
                           .add(jTextField4, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                       .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                       .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                           .add(jLabel5)
                           .add(jScrollPane2, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)))
                   .add(jScrollPane1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 210, Short.MAX_VALUE))
               .addContainerGap())
       );
       java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
       setBounds((screenSize.width-489)/2, (screenSize.height-266)/2, 489, 266);
   }// </editor-fold>//GEN-END:initComponents
   
   /**
    * @param args the command line arguments
    */
   public static void main(String args[]) {
       java.awt.EventQueue.invokeLater(new Runnable() {
           public void run() {
               new GlassMouseCursor().setVisible(true);
           }
       });
   }
   
   // Variables declaration - do not modify//GEN-BEGIN:variables
   // End of variables declaration//GEN-END:variables
   

} /*

* Copyright (c) 2007, Romain Guy
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
*   * Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*   * Redistributions in binary form must reproduce the above
*     copyright notice, this list of conditions and the following
*     disclaimer in the documentation and/or other materials provided
*     with the distribution.
*   * Neither the name of the TimingFramework project nor the names of its
*     contributors may be used to endorse or promote products derived
*     from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/**

*
* @author Romain Guy
*/

class WatermarkGlassPane extends JComponent {

   private BufferedImage image = null;
   
   /** Creates a new instance of WatermarkGlassPane */
   public WatermarkGlassPane() {
   }
   
   @Override
   public boolean contains(int x, int y) {
       if (getMouseListeners().length == 0 &&
           getMouseMotionListeners().length == 0 &&
           getMouseWheelListeners().length == 0 &&
           getCursor() == Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)) {
           if (image == null) {
               return false;
           } else {
               int imageX = getWidth() - image.getWidth();
               int imageY = getHeight() - image.getHeight();
               
               // if the mouse cursor is on a non-opaque pixel, mouse events
               // are allowed
               int inImageX = x - imageX;
               int inImageY = y - imageY;
               
               if (inImageX >= 0 && inImageY >= 0 &&
                   inImageX < image.getWidth() && inImageY < image.getHeight()) {
                   int color = image.getRGB(inImageX, inImageY);
                   return (color >> 24 & 0xFF) > 0;
               }
               
               return x > imageX && x < getWidth() &&
                      y > imageY && y < getHeight();
           }
       }
       return super.contains(x, y);
   }
   
   @Override
   protected void paintComponent(Graphics g) {
       if (image == null) {
           try {
               image = ImageIO.read(getClass().getResource("watermark.png"));
           } catch (IOException ex) {
               ex.printStackTrace();
           }
       }
       g.drawImage(image, getWidth() - image.getWidth(),
               getHeight() - image.getHeight(), null);
   }

}


      </source>
   
  
 
  



GlassPane Drag Drop

   <source lang="java">

/*

* Copyright (c) 2007, Romain Guy
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
*   * Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*   * Redistributions in binary form must reproduce the above
*     copyright notice, this list of conditions and the following
*     disclaimer in the documentation and/or other materials provided
*     with the distribution.
*   * Neither the name of the TimingFramework project nor the names of its
*     contributors may be used to endorse or promote products derived
*     from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

import java.awt.Color; import java.awt.Graphics; import java.awt.Point; import java.awt.Rectangle; import java.awt.image.BufferedImage; import javax.swing.JComponent; import javax.swing.SwingUtilities; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.MouseInfo; import java.awt.Point; import java.awt.Rectangle; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.image.BufferedImage; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.util.ArrayList; import java.util.List; import javax.imageio.ImageIO; import javax.swing.DefaultListModel; import javax.swing.ImageIcon; import javax.swing.JPanel; import javax.swing.TransferHandler; import javax.swing.TransferHandler.TransferSupport; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.Raster; import java.awt.image.WritableRaster; import java.awt.GraphicsConfiguration; import java.awt.Transparency; import java.awt.Graphics; import java.awt.GraphicsEnvironment; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.io.IOException; import java.net.URL; import javax.imageio.ImageIO; import java.awt.Color; import java.awt.image.BufferedImage; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; /**

*
* @author Romain Guy
*/

public class GlassPaneDragAndDrop extends javax.swing.JFrame {

   private PictureGlassPane glassPane = new PictureGlassPane();
   
   public GlassPaneDragAndDrop() {
       setContentPane(new JPanel(new BorderLayout()) {
           private BufferedImage image = null;
           
           @Override
           public boolean isOpaque() {
               return imageList.getModel().getSize() > 0;
           }
           
           @Override
           protected void paintComponent(Graphics g) {
               Rectangle clip = g.getClipBounds();
               
               g.setColor(Color.WHITE);
               g.fillRect(clip.x, clip.y, clip.width, clip.height);
               
               if (image == null) {
                   try {
                       image = ImageIO.read(getClass().getResource("drop-here.png"));
                   } catch (IOException ioe) {
                       ioe.printStackTrace();
                   }
               }
               
               g.drawImage(image, (getWidth() - image.getWidth()) / 2,
                       (getHeight() - image.getHeight()) / 2, null);
           }
       });
       
       initComponents();
       
       imageList.setOpaque(false);
       listScroller.setOpaque(false);
       listScroller.getViewport().setOpaque(false);
       
       setGlassPane(glassPane);
       imageList.setModel(new DefaultListModel());
       imageList.setTransferHandler(new FileDropHandler());
       imageList.addPropertyChangeListener("dropLocation", new PropertyChangeListener() {
           public void propertyChange(PropertyChangeEvent evt) {
               glassPane.moveIt(MouseInfo.getPointerInfo().getLocation());
           }
       });
   }
   
   /** This method is called from within the constructor to
    * initialize the form.
    * WARNING: Do NOT modify this code. The content of this method is
    * always regenerated by the Form Editor.
    */
   // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
   private void initComponents() {
       javax.swing.JLabel jLabel1;
       javax.swing.JLabel jLabel2;
       javax.swing.JLabel jLabel3;
       javax.swing.JPanel jPanel1;
       javax.swing.JSeparator jSeparator1;
       listScroller = new javax.swing.JScrollPane();
       imageList = new javax.swing.JList();
       jPanel1 = new javax.swing.JPanel();
       jLabel1 = new javax.swing.JLabel();
       jLabel2 = new javax.swing.JLabel();
       jLabel3 = new javax.swing.JLabel();
       jSeparator1 = new javax.swing.JSeparator();
       setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
       setTitle("Glass Drag and Drop");
       imageList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
       imageList.setLayoutOrientation(javax.swing.JList.HORIZONTAL_WRAP);
       imageList.setVisibleRowCount(-1);
       listScroller.setViewportView(imageList);
       jPanel1.setBackground(new java.awt.Color(255, 255, 255));
       jLabel1.setIcon(new javax.swing.ImageIcon(getClass().getResource("app-icon.png")));
       jLabel2.setFont(jLabel2.getFont().deriveFont(jLabel2.getFont().getStyle() | java.awt.Font.BOLD, jLabel2.getFont().getSize()+2));
       jLabel2.setText("Glass Drag and Drop");
       jLabel3.setText("Drag and drop image files (PNG or JPEG) onto the application.");
       org.jdesktop.layout.GroupLayout jPanel1Layout = new org.jdesktop.layout.GroupLayout(jPanel1);
       jPanel1.setLayout(jPanel1Layout);
       jPanel1Layout.setHorizontalGroup(
           jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
           .add(jPanel1Layout.createSequentialGroup()
               .addContainerGap()
               .add(jLabel1)
               .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
               .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                   .add(jLabel2)
                   .add(jLabel3))
               .addContainerGap(158, Short.MAX_VALUE))
       );
       jPanel1Layout.setVerticalGroup(
           jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
           .add(jPanel1Layout.createSequentialGroup()
               .addContainerGap()
               .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                   .add(jPanel1Layout.createSequentialGroup()
                       .add(jLabel2)
                       .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                       .add(jLabel3))
                   .add(jLabel1))
               .addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
       );
       org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane());
       getContentPane().setLayout(layout);
       layout.setHorizontalGroup(
           layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
           .add(jPanel1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
           .add(jSeparator1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 618, Short.MAX_VALUE)
           .add(layout.createSequentialGroup()
               .addContainerGap()
               .add(listScroller, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 578, Short.MAX_VALUE)
               .addContainerGap())
       );
       layout.setVerticalGroup(
           layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
           .add(layout.createSequentialGroup()
               .add(jPanel1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
               .add(0, 0, 0)
               .add(jSeparator1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 10, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
               .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
               .add(listScroller, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 372, Short.MAX_VALUE)
               .addContainerGap())
       );
       pack();
       java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
       java.awt.Dimension dialogSize = getSize();
       setLocation((screenSize.width-dialogSize.width)/2,(screenSize.height-dialogSize.height)/2);
   }// </editor-fold>//GEN-END:initComponents
   
   class FileDropHandler extends TransferHandler {
       private boolean imported = false;
       private List<File> fileList;
       
       public boolean canImport(TransferSupport support) {
           if (!support.isDrop()) {
               return false;
           }
           
           if (!support.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
               return false;
           }            
           boolean copySupported = (COPY & support.getSourceDropActions()) == COPY;
           if (copySupported) {
               support.setDropAction(COPY);
               
               if (!imported) {
                   Transferable t = support.getTransferable();
                   try {
                       Object data = t.getTransferData(DataFlavor.javaFileListFlavor);
                       this.fileList = (List<File>) data;
                       BufferedImage image = createImage(fileList);
                       
                       if (image != null) {
                           Point p = MouseInfo.getPointerInfo().getLocation();
                           glassPane.showIt(image, p);
                           imported = true;
                       }
                   } catch (UnsupportedFlavorException e) {
                       return false;
                   } catch (IOException e) {
                       return false;
                   }
               }
               return true;
           }
           
           return false;
       }
               
       private BufferedImage createImage(List<File> files) {
           List<File> imageFiles = new ArrayList<File>(3);
           for (File file : files) {
               if (file.getName().endsWith(".png") ||
                   file.getName().endsWith(".jpg")) {
                   imageFiles.add(file);
                   if (imageFiles.size() == 3) {
                       break;
                   }
               }
           }
           
           if (imageFiles.size() == 0) {
               return null;
           }
           
           int width = 60 + (imageFiles.size() - 1) * 10;
           int height = 45 + (imageFiles.size() - 1) * 10;
           
           BufferedImage image =
                   GraphicsUtilities.createCompatibleTranslucentImage(width, height);
           Graphics2D g2 = image.createGraphics();
           
           for (int i = 0; i < imageFiles.size(); i++) {
               File imageFile = imageFiles.get(i);
               BufferedImage externalImage = null;
               try {
                   externalImage = GraphicsUtilities.loadCompatibleImage(imageFile.toURI().toURL());
               } catch (MalformedURLException ex) {
                   ex.printStackTrace();
               } catch (IOException ex) {
                   ex.printStackTrace();
               }
               externalImage = GraphicsUtilities.createThumbnail(externalImage, 60, 45);
               g2.drawImage(externalImage, i * 10, i * 10, null);
           }
           
           g2.dispose();
           return image;
       }
       
       public boolean importData(TransferSupport support) {
           if (!canImport(support)) {
               return false;
           }
           
           if (!support.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
               return false;
           }
           
           for (int i = 0; i < fileList.size(); i++) {
               File imageFile = fileList.get(i);
               BufferedImage externalImage = null;
               try {
                   externalImage = GraphicsUtilities.loadCompatibleImage(imageFile.toURI().toURL());
                   externalImage = GraphicsUtilities.createThumbnail(externalImage, 120);
               } catch (MalformedURLException ex) {
                   ex.printStackTrace();
               } catch (IOException ex) {
                   ex.printStackTrace();
               }
               ((DefaultListModel) imageList.getModel()).add(0, new ImageIcon(externalImage));
           }
           glassPane.hideIt();
           imported = false;
           return true;
       }
   }
   
   /**
    * @param args the command line arguments
    */
   public static void main(String args[]) {
       java.awt.EventQueue.invokeLater(new Runnable() {
           public void run() {
               new GlassPaneDragAndDrop().setVisible(true);
           }
       });
   }
   
   // Variables declaration - do not modify//GEN-BEGIN:variables
   private javax.swing.JList imageList;
   private javax.swing.JScrollPane listScroller;
   // End of variables declaration//GEN-END:variables
   

} /*

* $Id: GraphicsUtilities.java,v 1.11 2007/04/29 22:33:33 gfx Exp $
*
* Dual-licensed under LGPL (Sun and Romain Guy) and BSD (Romain Guy).
*
* Copyright 2005 Sun Microsystems, Inc., 4150 Network Circle,
* Santa Clara, California 95054, U.S.A. All rights reserved.
*
* Copyright (c) 2006 Romain Guy <romain.guy@mac.ru>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
*    derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS"" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/**

*

GraphicsUtilities contains a set of tools to perform * common graphics operations easily. These operations are divided into * several themes, listed below.

*
*

Compatible Images

*
*

Compatible images can, and should, be used to increase drawing * performance. This class provides a number of methods to load compatible * images directly from files or to convert existing images to compatibles * images.

*
*

Creating Thumbnails

*
*

This class provides a number of methods to easily scale down images. * Some of these methods offer a trade-off between speed and result quality and * shouuld be used all the time. They also offer the advantage of producing * compatible images, thus automatically resulting into better runtime * performance.

*
*

All these methodes are both faster than * {@link java.awt.Image#getScaledInstance(int, int, int)} and produce * better-looking results than the various drawImage() methods * in {@link java.awt.Graphics}, which can be used for image scaling.

*

Image Manipulation

*
*

This class provides two methods to get and set pixels in a buffered image. * These methods try to avoid unmanaging the image in order to keep good * performance.

*
* @author Romain Guy <romain.guy@mac.ru>
* @author rbair
*/

class GraphicsUtilities {

   private GraphicsUtilities() {
   }
   // Returns the graphics configuration for the primary screen
   private static GraphicsConfiguration getGraphicsConfiguration() {
       return GraphicsEnvironment.getLocalGraphicsEnvironment().
                   getDefaultScreenDevice().getDefaultConfiguration();
   }
   private static boolean isHeadless() {
       return GraphicsEnvironment.isHeadless();
   }
   /**
*

Returns a new BufferedImage using the same color model * as the image passed as a parameter. The returned image is only compatible * with the image passed as a parameter. This does not mean the returned * image is compatible with the hardware.

    *
    * @param image the reference image from which the color model of the new
    *   image is obtained
    * @return a new BufferedImage, compatible with the color model
    *   of image
    */
   public static BufferedImage createColorModelCompatibleImage(BufferedImage image) {
       ColorModel cm = image.getColorModel();
       return new BufferedImage(cm,
           cm.createCompatibleWritableRaster(image.getWidth(),
                                             image.getHeight()),
           cm.isAlphaPremultiplied(), null);
   }
   /**
*

Returns a new compatible image with the same width, height and * transparency as the image specified as a parameter. That is, the * returned BufferedImage will be compatible with the graphics hardware. * If this method is called in a headless environment, then * the returned BufferedImage will be compatible with the source * image.

    *
    * @see java.awt.Transparency
    * @see #createCompatibleImage(int, int)
    * @see #createCompatibleImage(java.awt.image.BufferedImage, int, int)
    * @see #createCompatibleTranslucentImage(int, int)
    * @see #loadCompatibleImage(java.net.URL)
    * @see #toCompatibleImage(java.awt.image.BufferedImage)
    * @param image the reference image from which the dimension and the
    *   transparency of the new image are obtained
    * @return a new compatible BufferedImage with the same
    *   dimension and transparency as image
    */
   public static BufferedImage createCompatibleImage(BufferedImage image) {
       return createCompatibleImage(image, image.getWidth(), image.getHeight());
   }
   /**
*

Returns a new compatible image of the specified width and height, and * the same transparency setting as the image specified as a parameter. * That is, the returned BufferedImage is compatible with * the graphics hardware. If the method is called in a headless * environment, then the returned BufferedImage will be compatible with * the source image.

    *
    * @see java.awt.Transparency
    * @see #createCompatibleImage(java.awt.image.BufferedImage)
    * @see #createCompatibleImage(int, int)
    * @see #createCompatibleTranslucentImage(int, int)
    * @see #loadCompatibleImage(java.net.URL)
    * @see #toCompatibleImage(java.awt.image.BufferedImage)
    * @param width the width of the new image
    * @param height the height of the new image
    * @param image the reference image from which the transparency of the new
    *   image is obtained
    * @return a new compatible BufferedImage with the same
    *   transparency as image and the specified dimension
    */
   public static BufferedImage createCompatibleImage(BufferedImage image,
                                                     int width, int height) {
       return isHeadless() ?
               new BufferedImage(width, height, image.getType()) :
               getGraphicsConfiguration().createCompatibleImage(width, height,
                                                  image.getTransparency());
   }
   /**
*

Returns a new opaque compatible image of the specified width and * height. That is, the returned BufferedImage is compatible with * the graphics hardware. If the method is called in a headless * environment, then the returned BufferedImage will be compatible with * the source image.

    *
    * @see #createCompatibleImage(java.awt.image.BufferedImage)
    * @see #createCompatibleImage(java.awt.image.BufferedImage, int, int)
    * @see #createCompatibleTranslucentImage(int, int)
    * @see #loadCompatibleImage(java.net.URL)
    * @see #toCompatibleImage(java.awt.image.BufferedImage)
    * @param width the width of the new image
    * @param height the height of the new image
    * @return a new opaque compatible BufferedImage of the
    *   specified width and height
    */
   public static BufferedImage createCompatibleImage(int width, int height) {
       return isHeadless() ?
               new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB) :
               getGraphicsConfiguration().createCompatibleImage(width, height);
   }
   /**
*

Returns a new translucent compatible image of the specified width and * height. That is, the returned BufferedImage is compatible with * the graphics hardware. If the method is called in a headless * environment, then the returned BufferedImage will be compatible with * the source image.

    *
    * @see #createCompatibleImage(java.awt.image.BufferedImage)
    * @see #createCompatibleImage(java.awt.image.BufferedImage, int, int)
    * @see #createCompatibleImage(int, int)
    * @see #loadCompatibleImage(java.net.URL)
    * @see #toCompatibleImage(java.awt.image.BufferedImage)
    * @param width the width of the new image
    * @param height the height of the new image
    * @return a new translucent compatible BufferedImage of the
    *   specified width and height
    */
   public static BufferedImage createCompatibleTranslucentImage(int width,
                                                                int height) {
       return isHeadless() ?
               new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB) :
               getGraphicsConfiguration().createCompatibleImage(width, height,
                                                  Transparency.TRANSLUCENT);
   }
   /**
*

Returns a new compatible image from a URL. The image is loaded from the * specified location and then turned, if necessary into a compatible * image.

    *
    * @see #createCompatibleImage(java.awt.image.BufferedImage)
    * @see #createCompatibleImage(java.awt.image.BufferedImage, int, int)
    * @see #createCompatibleImage(int, int)
    * @see #createCompatibleTranslucentImage(int, int)
    * @see #toCompatibleImage(java.awt.image.BufferedImage)
    * @param resource the URL of the picture to load as a compatible image
    * @return a new translucent compatible BufferedImage of the
    *   specified width and height
    * @throws java.io.IOException if the image cannot be read or loaded
    */
   public static BufferedImage loadCompatibleImage(URL resource)
           throws IOException {
       BufferedImage image = ImageIO.read(resource);
       return toCompatibleImage(image);
   }
   /**
*

Return a new compatible image that contains a copy of the specified * image. This method ensures an image is compatible with the hardware, * and therefore optimized for fast blitting operations.

    *
*

If the method is called in a headless environment, then the returned * BufferedImage will be the source image.

    *
    * @see #createCompatibleImage(java.awt.image.BufferedImage)
    * @see #createCompatibleImage(java.awt.image.BufferedImage, int, int)
    * @see #createCompatibleImage(int, int)
    * @see #createCompatibleTranslucentImage(int, int)
    * @see #loadCompatibleImage(java.net.URL)
    * @param image the image to copy into a new compatible image
    * @return a new compatible copy, with the
    *   same width and height and transparency and content, of image
    */
   public static BufferedImage toCompatibleImage(BufferedImage image) {
       if (isHeadless()) {
           return image;
       }
       if (image.getColorModel().equals(
               getGraphicsConfiguration().getColorModel())) {
           return image;
       }
       BufferedImage compatibleImage =
               getGraphicsConfiguration().createCompatibleImage(
                   image.getWidth(), image.getHeight(),
                   image.getTransparency());
       Graphics g = compatibleImage.getGraphics();
       g.drawImage(image, 0, 0, null);
       g.dispose();
       return compatibleImage;
   }
   /**
*

Returns a thumbnail of a source image. newSize defines * the length of the longest dimension of the thumbnail. The other * dimension is then computed according to the dimensions ratio of the * original picture.

*

This method favors speed over quality. When the new size is less than * half the longest dimension of the source image, * {@link #createThumbnail(BufferedImage, int)} or * {@link #createThumbnail(BufferedImage, int, int)} should be used instead * to ensure the quality of the result without sacrificing too much * performance.

    *
    * @see #createThumbnailFast(java.awt.image.BufferedImage, int, int)
    * @see #createThumbnail(java.awt.image.BufferedImage, int)
    * @see #createThumbnail(java.awt.image.BufferedImage, int, int)
    * @param image the source image
    * @param newSize the length of the largest dimension of the thumbnail
    * @return a new compatible BufferedImage containing a
    *   thumbnail of image
    * @throws IllegalArgumentException if newSize is larger than
    *   the largest dimension of image or <= 0
    */
   public static BufferedImage createThumbnailFast(BufferedImage image,
                                                   int newSize) {
       float ratio;
       int width = image.getWidth();
       int height = image.getHeight();
       if (width > height) {
           if (newSize >= width) {
               throw new IllegalArgumentException("newSize must be lower than" +
                                                  " the image width");
           } else if (newSize <= 0) {
                throw new IllegalArgumentException("newSize must" +
                                                   " be greater than 0");
           }
           ratio = (float) width / (float) height;
           width = newSize;
           height = (int) (newSize / ratio);
       } else {
           if (newSize >= height) {
               throw new IllegalArgumentException("newSize must be lower than" +
                                                  " the image height");
           } else if (newSize <= 0) {
                throw new IllegalArgumentException("newSize must" +
                                                   " be greater than 0");
           }
           ratio = (float) height / (float) width;
           height = newSize;
           width = (int) (newSize / ratio);
       }
       BufferedImage temp = createCompatibleImage(image, width, height);
       Graphics2D g2 = temp.createGraphics();
       g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                           RenderingHints.VALUE_INTERPOLATION_BILINEAR);
       g2.drawImage(image, 0, 0, temp.getWidth(), temp.getHeight(), null);
       g2.dispose();
       return temp;
   }
   /**
*

Returns a thumbnail of a source image.

*

This method favors speed over quality. When the new size is less than * half the longest dimension of the source image, * {@link #createThumbnail(BufferedImage, int)} or * {@link #createThumbnail(BufferedImage, int, int)} should be used instead * to ensure the quality of the result without sacrificing too much * performance.

    *
    * @see #createThumbnailFast(java.awt.image.BufferedImage, int)
    * @see #createThumbnail(java.awt.image.BufferedImage, int)
    * @see #createThumbnail(java.awt.image.BufferedImage, int, int)
    * @param image the source image
    * @param newWidth the width of the thumbnail
    * @param newHeight the height of the thumbnail
    * @return a new compatible BufferedImage containing a
    *   thumbnail of image
    * @throws IllegalArgumentException if newWidth is larger than
    *   the width of image or if code>newHeight</code> is larger
    *   than the height of image or if one of the dimensions
    *   is <= 0
    */
   public static BufferedImage createThumbnailFast(BufferedImage image,
                                                   int newWidth, int newHeight) {
       if (newWidth >= image.getWidth() ||
           newHeight >= image.getHeight()) {
           throw new IllegalArgumentException("newWidth and newHeight cannot" +
                                              " be greater than the image" +
                                              " dimensions");
       } else if (newWidth <= 0 || newHeight <= 0) {
           throw new IllegalArgumentException("newWidth and newHeight must" +
                                              " be greater than 0");
       }
       BufferedImage temp = createCompatibleImage(image, newWidth, newHeight);
       Graphics2D g2 = temp.createGraphics();
       g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                           RenderingHints.VALUE_INTERPOLATION_BILINEAR);
       g2.drawImage(image, 0, 0, temp.getWidth(), temp.getHeight(), null);
       g2.dispose();
       return temp;
   }
   /**
*

Returns a thumbnail of a source image. newSize defines * the length of the longest dimension of the thumbnail. The other * dimension is then computed according to the dimensions ratio of the * original picture.

*

This method offers a good trade-off between speed and quality. * The result looks better than * {@link #createThumbnailFast(java.awt.image.BufferedImage, int)} when * the new size is less than half the longest dimension of the source * image, yet the rendering speed is almost similar.

    *
    * @see #createThumbnailFast(java.awt.image.BufferedImage, int, int)
    * @see #createThumbnailFast(java.awt.image.BufferedImage, int)
    * @see #createThumbnail(java.awt.image.BufferedImage, int, int)
    * @param image the source image
    * @param newSize the length of the largest dimension of the thumbnail
    * @return a new compatible BufferedImage containing a
    *   thumbnail of image
    * @throws IllegalArgumentException if newSize is larger than
    *   the largest dimension of image or <= 0
    */
   public static BufferedImage createThumbnail(BufferedImage image,
                                               int newSize) {
       int width = image.getWidth();
       int height = image.getHeight();
       boolean isTranslucent = image.getTransparency() != Transparency.OPAQUE;
       boolean isWidthGreater = width > height;
       if (isWidthGreater) {
           if (newSize >= width) {
               throw new IllegalArgumentException("newSize must be lower than" +
                                                  " the image width");
           }
       } else if (newSize >= height) {
           throw new IllegalArgumentException("newSize must be lower than" +
                                              " the image height");
       }
       if (newSize <= 0) {
           throw new IllegalArgumentException("newSize must" +
                                              " be greater than 0");
       }
       float ratioWH = (float) width / (float) height;
       float ratioHW = (float) height / (float) width;
       BufferedImage thumb = image;
       BufferedImage temp = null;
       Graphics2D g2 = null;
       int previousWidth = width;
       int previousHeight = height;
       do {
           if (isWidthGreater) {
               width /= 2;
               if (width < newSize) {
                   width = newSize;
               }
               height = (int) (width / ratioWH);
           } else {
               height /= 2;
               if (height < newSize) {
                   height = newSize;
               }
               width = (int) (height / ratioHW);
           }
           if (temp == null || isTranslucent) {
               temp = createCompatibleImage(image, width, height);
               g2 = temp.createGraphics();
               g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                               RenderingHints.VALUE_INTERPOLATION_BILINEAR);
           }
           g2.drawImage(thumb, 0, 0, width, height,
                   0, 0, previousWidth, previousHeight, null);
           previousWidth = width;
           previousHeight = height;
           thumb = temp;
       } while (newSize != (isWidthGreater ? width : height));
       g2.dispose();
       if (width != thumb.getWidth() || height != thumb.getHeight()) {
           temp = createCompatibleImage(image, width, height);
           g2 = temp.createGraphics();
           g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                               RenderingHints.VALUE_INTERPOLATION_BILINEAR);
           g2.drawImage(thumb, 0, 0, width, height, null);
           g2.dispose();
           thumb = temp;
       }
       return thumb;
   }
   /**
*

Returns a thumbnail of a source image.

*

This method offers a good trade-off between speed and quality. * The result looks better than * {@link #createThumbnailFast(java.awt.image.BufferedImage, int)} when * the new size is less than half the longest dimension of the source * image, yet the rendering speed is almost similar.

    *
    * @see #createThumbnailFast(java.awt.image.BufferedImage, int)
    * @see #createThumbnailFast(java.awt.image.BufferedImage, int, int)
    * @see #createThumbnail(java.awt.image.BufferedImage, int)
    * @param image the source image
    * @param newWidth the width of the thumbnail
    * @param newHeight the height of the thumbnail
    * @return a new compatible BufferedImage containing a
    *   thumbnail of image
    * @throws IllegalArgumentException if newWidth is larger than
    *   the width of image or if code>newHeight</code> is larger
    *   than the height of image or if one the dimensions is not > 0
    */
   public static BufferedImage createThumbnail(BufferedImage image,
                                               int newWidth, int newHeight) {
       int width = image.getWidth();
       int height = image.getHeight();
       boolean isTranslucent = image.getTransparency() != Transparency.OPAQUE;
       if (newWidth >= width || newHeight >= height) {
           throw new IllegalArgumentException("newWidth and newHeight cannot" +
                                              " be greater than the image" +
                                              " dimensions");
       } else if (newWidth <= 0 || newHeight <= 0) {
           throw new IllegalArgumentException("newWidth and newHeight must" +
                                              " be greater than 0");
       }
       BufferedImage thumb = image;
       BufferedImage temp = null;
       Graphics2D g2 = null;
       int previousWidth = width;
       int previousHeight = height;
       do {
           if (width > newWidth) {
               width /= 2;
               if (width < newWidth) {
                   width = newWidth;
               }
           }
           if (height > newHeight) {
               height /= 2;
               if (height < newHeight) {
                   height = newHeight;
               }
           }
           if (temp == null || isTranslucent) {
               temp = createCompatibleImage(image, width, height);
               g2 = temp.createGraphics();
               g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                               RenderingHints.VALUE_INTERPOLATION_BILINEAR);
           }
           g2.drawImage(thumb, 0, 0, width, height,
                        0, 0, previousWidth, previousHeight, null);
           previousWidth = width;
           previousHeight = height;
           thumb = temp;
       } while (width != newWidth || height != newHeight);
       g2.dispose();
       if (width != thumb.getWidth() || height != thumb.getHeight()) {
           temp = createCompatibleImage(image, width, height);
           g2 = temp.createGraphics();
           g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                               RenderingHints.VALUE_INTERPOLATION_BILINEAR);
           g2.drawImage(thumb, 0, 0, width, height, null);
           g2.dispose();
           thumb = temp;
       }
       return thumb;
   }
   /**
*

Returns an array of pixels, stored as integers, from a * BufferedImage. The pixels are grabbed from a rectangular * area defined by a location and two dimensions. Calling this method on * an image of type different from BufferedImage.TYPE_INT_ARGB * and BufferedImage.TYPE_INT_RGB will unmanage the image.

    *
    * @param img the source image
    * @param x the x location at which to start grabbing pixels
    * @param y the y location at which to start grabbing pixels
    * @param w the width of the rectangle of pixels to grab
    * @param h the height of the rectangle of pixels to grab
    * @param pixels a pre-allocated array of pixels of size w*h; can be null
    * @return pixels if non-null, a new array of integers
    *   otherwise
    * @throws IllegalArgumentException is pixels is non-null and
    *   of length < w*h
    */
   public static int[] getPixels(BufferedImage img,
                                 int x, int y, int w, int h, int[] pixels) {
       if (w == 0 || h == 0) {
           return new int[0];
       }
       if (pixels == null) {
           pixels = new int[w * h];
       } else if (pixels.length < w * h) {
           throw new IllegalArgumentException("pixels array must have a length" +
                                              " >= w*h");
       }
       int imageType = img.getType();
       if (imageType == BufferedImage.TYPE_INT_ARGB ||
           imageType == BufferedImage.TYPE_INT_RGB) {
           Raster raster = img.getRaster();
           return (int[]) raster.getDataElements(x, y, w, h, pixels);
       }
       // Unmanages the image
       return img.getRGB(x, y, w, h, pixels, 0, w);
   }
   /**
*

Writes a rectangular area of pixels in the destination * BufferedImage. Calling this method on * an image of type different from BufferedImage.TYPE_INT_ARGB * and BufferedImage.TYPE_INT_RGB will unmanage the image.

    *
    * @param img the destination image
    * @param x the x location at which to start storing pixels
    * @param y the y location at which to start storing pixels
    * @param w the width of the rectangle of pixels to store
    * @param h the height of the rectangle of pixels to store
    * @param pixels an array of pixels, stored as integers
    * @throws IllegalArgumentException is pixels is non-null and
    *   of length < w*h
    */
   public static void setPixels(BufferedImage img,
                                int x, int y, int w, int h, int[] pixels) {
       if (pixels == null || w == 0 || h == 0) {
           return;
       } else if (pixels.length < w * h) {
           throw new IllegalArgumentException("pixels array must have a length" +
                                              " >= w*h");
       }
       int imageType = img.getType();
       if (imageType == BufferedImage.TYPE_INT_ARGB ||
           imageType == BufferedImage.TYPE_INT_RGB) {
           WritableRaster raster = img.getRaster();
           raster.setDataElements(x, y, w, h, pixels);
       } else {
           // Unmanages the image
           img.setRGB(x, y, w, h, pixels, 0, w);
       }
   }

} /*

* Copyright (c) 2007, Romain Guy
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
*   * Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*   * Redistributions in binary form must reproduce the above
*     copyright notice, this list of conditions and the following
*     disclaimer in the documentation and/or other materials provided
*     with the distribution.
*   * Neither the name of the TimingFramework project nor the names of its
*     contributors may be used to endorse or promote products derived
*     from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/**

*
* @author Romain Guy
*/

class PictureGlassPane extends JComponent {

   private BufferedImage image;
   private Point location;
   private BufferedImage shadow;
   
   public PictureGlassPane() {
   }
   
   public void moveIt(Point location) {
       Point oldLocation = this.location;
       SwingUtilities.convertPointFromScreen(location, this);
       this.location = location;
       
       Rectangle newClip = new Rectangle(location.x - image.getWidth() / 2, location.y - image.getHeight() / 2,
               image.getWidth(), image.getHeight());
       newClip.add(new Rectangle(oldLocation.x - image.getWidth() / 2, oldLocation.y - image.getHeight() / 2,
               image.getWidth(), image.getHeight()));
       newClip.add(new Rectangle(oldLocation.x - image.getWidth() / 2, oldLocation.y - image.getHeight() / 2,
               shadow.getWidth(), shadow.getHeight()));
       newClip.add(new Rectangle(location.x - image.getWidth() / 2, location.y - image.getHeight() / 2,
               shadow.getWidth(), shadow.getHeight()));
       repaint(newClip);
   }
   
   public void hideIt() {
       setVisible(false);
   }
   
   public void showIt(BufferedImage image, Point location) {
       this.image = image;
       this.shadow = new ShadowRenderer(5, 0.3f, Color.BLACK).createShadow(image);
       SwingUtilities.convertPointFromScreen(location, this);
       this.location = location;
       
       setVisible(true);
   }
   
   @Override
   protected void paintComponent(Graphics g) {
       if (image != null && location != null) {
           int x = location.x - image.getWidth() / 2;
           int y = location.y - image.getHeight() / 2;
           
           g.drawImage(shadow, x, y, null);
           g.drawImage(image, x, y, null);
       }
   }

} /*

* $Id: ShadowRenderer.java,v 1.1 2007/01/15 23:39:23 gfx Exp $
*
* Copyright 2006 Sun Microsystems, Inc., 4150 Network Circle,
* Santa Clara, California 95054, U.S.A. All rights reserved.
*
* Licensed under LGPL.
*/

/**

*

A shadow renderer generates a drop shadow for any given picture, respecting * the transparency channel if present. The resulting picture contains the * shadow only and to create a drop shadow effect you will need to stack the * original picture and the shadow generated by the renderer.

*

Shadow Properties

*

A shadow is defined by three properties: *

    *
  • size: The size, in pixels, of the shadow. This property also * defines the fuzzyness.
  • *
  • opacity: The opacity, between 0.0 and 1.0, of the shadow.
  • *
  • color: The color of the shadow. Shadows are not meant to be * black only.
  • *
* You can set these properties using the provided mutaters or the appropriate
* constructor. Here are two ways of creating a green shadow of size 10 and
* with an opacity of 50%:
*
 * ShadowRenderer renderer = new ShadowRenderer(10, 0.5f, Color.GREEN);
 * // ..
 * renderer = new ShadowRenderer();
 * renderer.setSize(10);
 * renderer.setOpacity(0.5f);
 * renderer.setColor(Color.GREEN);
 * 
* The default constructor provides the following default values:
*
    *
  • size: 5 pixels
  • *
  • opacity: 50%
  • *
  • color: Black
  • *

*

Generating a Shadow

*

A shadow is generated as a BufferedImage from another * BufferedImage. Once the renderer is set up, you must call * {@link #createShadow} to actually generate the shadow: *

 * ShadowRenderer renderer = new ShadowRenderer();
 * // renderer setup
 * BufferedImage shadow = renderer.createShadow(bufferedImage);
 * 

*

The generated image dimensions are computed as following:

*
 * width  = imageWidth  + 2 * shadowSize
 * height = imageHeight + 2 * shadowSize
 * 
*

Properties Changes

*

This renderer allows to register property change listeners with * {@link #addPropertyChangeListener}. Listening to properties changes is very * useful when you emebed the renderer in a graphical component and give the API * user the ability to access the renderer. By listening to properties changes, * you can easily repaint the component when needed.

*

Threading Issues

*

ShadowRenderer is not guaranteed to be thread-safe.

* 
* @author Romain Guy <romain.guy@mac.ru>
* @author Sebastien Petrucci
*/

class ShadowRenderer {

   /**
*

Identifies a change to the size used to render the shadow.

*

When the property change event is fired, the old value and the new * value are provided as Integer instances.

    */
   public static final String SIZE_CHANGED_PROPERTY = "shadow_size";
   
   /**
*

Identifies a change to the opacity used to render the shadow.

*

When the property change event is fired, the old value and the new * value are provided as Float instances.

    */
   public static final String OPACITY_CHANGED_PROPERTY = "shadow_opacity";
   
   /**
*

Identifies a change to the color used to render the shadow.

    */
   public static final String COLOR_CHANGED_PROPERTY = "shadow_color";
   // size of the shadow in pixels (defines the fuzziness)
   private int size = 5;
   
   // opacity of the shadow
   private float opacity = 0.5f;
   
   // color of the shadow
   private Color color = Color.BLACK;
   
   // notifies listeners of properties changes
   private PropertyChangeSupport changeSupport;
   /**
*

Creates a default good looking shadow generator. * The default shadow renderer provides the following default values: *

    *
  • size: 5 pixels
  • *
  • opacity: 50%
  • *
  • color: Black
  • *

*

These properties provide a regular, good looking shadow.

    */
   public ShadowRenderer() {
       this(5, 0.5f, Color.BLACK);
   }
   
   /**
*

A shadow renderer needs three properties to generate shadows. * These properties are:

*
    *
  • size: The size, in pixels, of the shadow. This property also * defines the fuzzyness.
  • *
  • opacity: The opacity, between 0.0 and 1.0, of the shadow.
  • *
  • color: The color of the shadow. Shadows are not meant to be * black only.
  • *
    * @param size the size of the shadow in pixels. Defines the fuzziness.
    * @param opacity the opacity of the shadow.
    * @param color the color of the shadow.
    */
   public ShadowRenderer(final int size, final float opacity, final Color color) {
       //noinspection ThisEscapedInObjectConstruction
       changeSupport = new PropertyChangeSupport(this);
       setSize(size);
       setOpacity(opacity);
       setColor(color);
   }
   /**
*

Add a PropertyChangeListener to the listener list. The listener is * registered for all properties. The same listener object may be added * more than once, and will be called as many times as it is added. If * listener is null, no exception is thrown and no action * is taken.

    * @param listener the PropertyChangeListener to be added
    */
   public void addPropertyChangeListener(PropertyChangeListener listener) {
       changeSupport.addPropertyChangeListener(listener);
   }
   /**
*

Remove a PropertyChangeListener from the listener list. This removes * a PropertyChangeListener that was registered for all properties. If * listener was added more than once to the same event source, * it will be notified one less time after being removed. If * listener is null, or was never added, no exception is thrown * and no action is taken.

    * @param listener the PropertyChangeListener to be removed
    */
   public void removePropertyChangeListener(PropertyChangeListener listener) {
       changeSupport.removePropertyChangeListener(listener);
   }
   /**
*

Gets the color used by the renderer to generate shadows.

    * @return this renderer"s shadow color
    */
   public Color getColor() {
       return color;
   }
   /**
*

Sets the color used by the renderer to generate shadows.

*

Consecutive calls to {@link #createShadow} will all use this color * until it is set again.

*

If the color provided is null, the previous color will be retained.

    * @param shadowColor the generated shadows color
    */
   public void setColor(final Color shadowColor) {
       if (shadowColor != null) {
           Color oldColor = this.color;
           this.color = shadowColor;
           changeSupport.firePropertyChange(COLOR_CHANGED_PROPERTY,
                                            oldColor,
                                            this.color);
       }
   }
   /**
*

Gets the opacity used by the renderer to generate shadows.

*

The opacity is comprised between 0.0f and 1.0f; 0.0f being fully * transparent and 1.0f fully opaque.

    * @return this renderer"s shadow opacity
    */
   public float getOpacity() {
       return opacity;
   }
   /**
*

Sets the opacity used by the renderer to generate shadows.

*

Consecutive calls to {@link #createShadow} will all use this opacity * until it is set again.

*

The opacity is comprised between 0.0f and 1.0f; 0.0f being fully * transparent and 1.0f fully opaque. If you provide a value out of these * boundaries, it will be restrained to the closest boundary.

    * @param shadowOpacity the generated shadows opacity
    */
   public void setOpacity(final float shadowOpacity) {
       float oldOpacity = this.opacity;
       
       if (shadowOpacity < 0.0) {
           this.opacity = 0.0f;
       } else if (shadowOpacity > 1.0f) {
           this.opacity = 1.0f;
       } else {
           this.opacity = shadowOpacity;
       }
       
       changeSupport.firePropertyChange(OPACITY_CHANGED_PROPERTY,
                                        oldOpacity,
                                        this.opacity);
   }
   /**
*

Gets the size in pixel used by the renderer to generate shadows.

    * @return this renderer"s shadow size
    */
   public int getSize() {
       return size;
   }
   /**
*

Sets the size, in pixels, used by the renderer to generate shadows.

*

The size defines the blur radius applied to the shadow to create the * fuzziness.

*

There is virtually no limit to the size. The size cannot be negative. * If you provide a negative value, the size will be 0 instead.

    * @param shadowSize the generated shadows size in pixels (fuzziness)
    */
   public void setSize(final int shadowSize) {
       int oldSize = this.size;
       
       if (shadowSize < 0) {
           this.size = 0;
       } else {
           this.size = shadowSize;
       }
       
       changeSupport.firePropertyChange(SIZE_CHANGED_PROPERTY,
                                        new Integer(oldSize),
                                        new Integer(this.size));
   }
   /**
*

Generates the shadow for a given picture and the current properties * of the renderer.

*

The generated image dimensions are computed as following:

*
     * width  = imageWidth  + 2 * shadowSize
     * height = imageHeight + 2 * shadowSize
     * 
    * @param image the picture from which the shadow must be cast
    * @return the picture containing the shadow of image 
    */
   public BufferedImage createShadow(final BufferedImage image) {
       // Written by Sesbastien Petrucci
       int shadowSize = size * 2;
       int srcWidth = image.getWidth();
       int srcHeight = image.getHeight();
       int dstWidth = srcWidth + shadowSize;
       int dstHeight = srcHeight + shadowSize;
       int left = size;
       int right = shadowSize - left;
       int yStop = dstHeight - right;
       int shadowRgb = color.getRGB() & 0x00FFFFFF;
       int[] aHistory = new int[shadowSize];
       int historyIdx;
       int aSum;
       BufferedImage dst = new BufferedImage(dstWidth, dstHeight,
                                             BufferedImage.TYPE_INT_ARGB);
       int[] dstBuffer = new int[dstWidth * dstHeight];
       int[] srcBuffer = new int[srcWidth * srcHeight];
       GraphicsUtilities.getPixels(image, 0, 0, srcWidth, srcHeight, srcBuffer);
       int lastPixelOffset = right * dstWidth;
       float hSumDivider = 1.0f / shadowSize;
       float vSumDivider = opacity / shadowSize;
       int[] hSumLookup = new int[256 * shadowSize];
       for (int i = 0; i < hSumLookup.length; i++) {
           hSumLookup[i] = (int) (i * hSumDivider);
       }
       int[] vSumLookup = new int[256 * shadowSize];
       for (int i = 0; i < vSumLookup.length; i++) {
           vSumLookup[i] = (int) (i * vSumDivider);
       }
       int srcOffset;
       // horizontal pass : extract the alpha mask from the source picture and
       // blur it into the destination picture
       for (int srcY = 0, dstOffset = left * dstWidth; srcY < srcHeight; srcY++) {
           // first pixels are empty
           for (historyIdx = 0; historyIdx < shadowSize; ) {
               aHistory[historyIdx++] = 0;
           }
           aSum = 0;
           historyIdx = 0;
           srcOffset = srcY * srcWidth;
           // compute the blur average with pixels from the source image
           for (int srcX = 0; srcX < srcWidth; srcX++) {
               int a = hSumLookup[aSum];
               dstBuffer[dstOffset++] = a << 24;   // store the alpha value only
                                                   // the shadow color will be added in the next pass
               aSum -= aHistory[historyIdx]; // substract the oldest pixel from the sum
               // extract the new pixel ...
               a = srcBuffer[srcOffset + srcX] >>> 24;
               aHistory[historyIdx] = a;   // ... and store its value into history
               aSum += a;                  // ... and add its value to the sum
               if (++historyIdx >= shadowSize) {
                   historyIdx -= shadowSize;
               }
           }
           // blur the end of the row - no new pixels to grab
           for (int i = 0; i < shadowSize; i++) {
               int a = hSumLookup[aSum];
               dstBuffer[dstOffset++] = a << 24;
               // substract the oldest pixel from the sum ... and nothing new to add !
               aSum -= aHistory[historyIdx];
               if (++historyIdx >= shadowSize) {
                   historyIdx -= shadowSize;
               }
           }
       }
       // vertical pass
       for (int x = 0, bufferOffset = 0; x < dstWidth; x++, bufferOffset = x) {
           aSum = 0;
           // first pixels are empty
           for (historyIdx = 0; historyIdx < left;) {
               aHistory[historyIdx++] = 0;
           }
           // and then they come from the dstBuffer
           for (int y = 0; y < right; y++, bufferOffset += dstWidth) {
               int a = dstBuffer[bufferOffset] >>> 24;         // extract alpha
               aHistory[historyIdx++] = a;                     // store into history
               aSum += a;                                      // and add to sum
           }
           bufferOffset = x;
           historyIdx = 0;
           // compute the blur avera`ge with pixels from the previous pass
           for (int y = 0; y < yStop; y++, bufferOffset += dstWidth) {
               int a = vSumLookup[aSum];
               dstBuffer[bufferOffset] = a << 24 | shadowRgb;  // store alpha value + shadow color
               aSum -= aHistory[historyIdx];   // substract the oldest pixel from the sum
               a = dstBuffer[bufferOffset + lastPixelOffset] >>> 24;   // extract the new pixel ...
               aHistory[historyIdx] = a;                               // ... and store its value into history
               aSum += a;                                              // ... and add its value to the sum
               if (++historyIdx >= shadowSize) {
                   historyIdx -= shadowSize;
               }
           }
           // blur the end of the column - no pixels to grab anymore
           for (int y = yStop; y < dstHeight; y++, bufferOffset += dstWidth) {
               int a = vSumLookup[aSum];
               dstBuffer[bufferOffset] = a << 24 | shadowRgb;
               aSum -= aHistory[historyIdx];   // substract the oldest pixel from the sum
               if (++historyIdx >= shadowSize) {
                   historyIdx -= shadowSize;
               }
           }
       }
       GraphicsUtilities.setPixels(dst, 0, 0, dstWidth, dstHeight, dstBuffer);
       return dst;
   }

}


      </source>
   
  
 
  



GlassPane Intercepts Event

   <source lang="java">

/*

* Copyright (c) 2007, Romain Guy
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
*   * Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*   * Redistributions in binary form must reproduce the above
*     copyright notice, this list of conditions and the following
*     disclaimer in the documentation and/or other materials provided
*     with the distribution.
*   * Neither the name of the TimingFramework project nor the names of its
*     contributors may be used to endorse or promote products derived
*     from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

import java.awt.AlphaComposite; import java.awt.Color; import java.awt.ruposite; import java.awt.Font; import java.awt.FontMetrics; import java.awt.GradientPaint; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.LinearGradientPaint; import java.awt.Paint; import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.event.ruponentAdapter; import java.awt.event.ruponentEvent; import java.awt.event.KeyAdapter; import java.awt.event.MouseAdapter; import java.awt.event.MouseMotionAdapter; import javax.swing.JComponent; /**

*
* @author Romain Guy
*/

public class GlassPaneInterceptEvent extends javax.swing.JFrame {

   private static final int MAX_DELAY = 300;
   
   private ProgressGlassPane glassPane;
   
   public GlassPaneInterceptEvent() {
       initComponents();
       setGlassPane(glassPane = new ProgressGlassPane());
   }
   
   /** This method is called from within the constructor to
    * initialize the form.
    * WARNING: Do NOT modify this code. The content of this method is
    * always regenerated by the Form Editor.
    */
   // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
   private void initComponents() {
       javax.swing.JButton buttonDownload;
       javax.swing.JLabel jLabel1;
       javax.swing.JScrollPane jScrollPane1;
       jLabel1 = new javax.swing.JLabel();
       buttonDownload = new javax.swing.JButton();
       jScrollPane1 = new javax.swing.JScrollPane();
       filesTable = new javax.swing.JTable();
       setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
       setTitle("Glass Pane Painting");
       setResizable(false);
       jLabel1.setText("Pick a file for download");
       buttonDownload.setText("Start Download");
       buttonDownload.addActionListener(new java.awt.event.ActionListener() {
           public void actionPerformed(java.awt.event.ActionEvent evt) {
               buttonDownloadActionPerformed(evt);
           }
       });
       filesTable.setModel(new javax.swing.table.DefaultTableModel(
           new Object [][] {
               {"aerith.png", "/www/progx/images/", "PNG", "5/17/2006"},
               {"blog.html", "/www/progx", "HTML", "3/1/2006"},
               {"index.html", "/www/progx", "HTML", "9/12/2006"},
               {"pictures.zip", "/www/progx", "ZIP", "10/8/2006"}
           },
           new String [] {
               "Name", "Path", "Type", "Date"
           }
       ));
       jScrollPane1.setViewportView(filesTable);
       org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane());
       getContentPane().setLayout(layout);
       layout.setHorizontalGroup(
           layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
           .add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup()
               .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
                   .add(layout.createSequentialGroup()
                       .addContainerGap()
                       .add(buttonDownload))
                   .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                       .add(layout.createSequentialGroup()
                           .addContainerGap()
                           .add(jLabel1))
                       .add(layout.createSequentialGroup()
                           .addContainerGap()
                           .add(jScrollPane1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 513, Short.MAX_VALUE))))
               .addContainerGap())
       );
       layout.setVerticalGroup(
           layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
           .add(layout.createSequentialGroup()
               .add(20, 20, 20)
               .add(jLabel1)
               .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
               .add(jScrollPane1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 275, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
               .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
               .add(buttonDownload)
               .addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
       );
       java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
       setBounds((screenSize.width-553)/2, (screenSize.height-394)/2, 553, 394);
   }// </editor-fold>//GEN-END:initComponents
   private void buttonDownloadActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonDownloadActionPerformed
       getGlassPane().setVisible(true);
       startDownloadThread();
   }//GEN-LAST:event_buttonDownloadActionPerformed
   
   private void startDownloadThread() {
       Thread downloader = new Thread(new Runnable() {
           public void run() {
               int i = 0;
               do {
                   try {
                       Thread.sleep(30 + (int) (Math.random() * MAX_DELAY));
                   } catch (InterruptedException ex) {
                       // who cares here?
                   }
                   i += (int) (Math.random() * 5);
                   glassPane.setProgress(i);
               } while (i < 100);
               glassPane.setVisible(false);
               glassPane.setProgress(0);
           }
       });
       downloader.start();
   }
   
   /**
    * @param args the command line arguments
    */
   public static void main(String args[]) {
       java.awt.EventQueue.invokeLater(new Runnable() {
           public void run() {
               new GlassPaneInterceptEvent().setVisible(true);
           }
       });
   }
   
   // Variables declaration - do not modify//GEN-BEGIN:variables
   private javax.swing.JTable filesTable;
   // End of variables declaration//GEN-END:variables
   

} /*

* Copyright (c) 2007, Romain Guy
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
*   * Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*   * Redistributions in binary form must reproduce the above
*     copyright notice, this list of conditions and the following
*     disclaimer in the documentation and/or other materials provided
*     with the distribution.
*   * Neither the name of the TimingFramework project nor the names of its
*     contributors may be used to endorse or promote products derived
*     from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/**

*
* @author Romain Guy
*/

class ProgressGlassPane extends JComponent {

   private static final int BAR_WIDTH = 200;
   private static final int BAR_HEIGHT = 10;
   
   private static final Color TEXT_COLOR = new Color(0x333333);
   private static final Color BORDER_COLOR = new Color(0x333333);
   
   private static final float[] GRADIENT_FRACTIONS = new float[] {
       0.0f, 0.499f, 0.5f, 1.0f
   };
   private static final Color[] GRADIENT_COLORS = new Color[] {
       Color.GRAY, Color.DARK_GRAY, Color.BLACK, Color.GRAY
   };
   private static final Color GRADIENT_COLOR2 = Color.WHITE;
   private static final Color GRADIENT_COLOR1 = Color.GRAY;
   private String message = "Downloading file...";
   private int progress = 0;
   
   /** Creates a new instance of ProgressGlassPane */
   public ProgressGlassPane() {
       // blocks all user input
       addMouseListener(new MouseAdapter() { });
       addMouseMotionListener(new MouseMotionAdapter() { });
       addKeyListener(new KeyAdapter() { });
       
       setFocusTraversalKeysEnabled(false);
       addComponentListener(new ComponentAdapter() {
           public void componentShown(ComponentEvent evt) {
               requestFocusInWindow();
           }
       });
       
       setBackground(Color.WHITE);
       setFont(new Font("Default", Font.BOLD, 16));
   }
   public int getProgress() {
       return progress;
   }
   public void setProgress(int progress) {
       int oldProgress = this.progress;
       this.progress = progress;
       
       // computes the damaged area
       FontMetrics metrics = getGraphics().getFontMetrics(getFont()); 
       int w = (int) (BAR_WIDTH * ((float) oldProgress / 100.0f));
       int x = w + (getWidth() - BAR_WIDTH) / 2;
       int y = (getHeight() - BAR_HEIGHT) / 2;
       y += metrics.getDescent() / 2;
       
       w = (int) (BAR_WIDTH * ((float) progress / 100.0f)) - w;
       int h = BAR_HEIGHT;
       
       repaint(x, y, w, h);
   }
   
   @Override
   protected void paintComponent(Graphics g) {
       // enables anti-aliasing
       Graphics2D g2 = (Graphics2D) g;
       g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
               RenderingHints.VALUE_ANTIALIAS_ON);
       
       // gets the current clipping area
       Rectangle clip = g.getClipBounds();
       
       // sets a 65% translucent composite
       AlphaComposite alpha = AlphaComposite.SrcOver.derive(0.65f);
       Composite composite = g2.getComposite();
       g2.setComposite(alpha);
       
       // fills the background
       g2.setColor(getBackground());
       g2.fillRect(clip.x, clip.y, clip.width, clip.height);
       
       // centers the progress bar on screen
       FontMetrics metrics = g.getFontMetrics();        
       int x = (getWidth() - BAR_WIDTH) / 2;
       int y = (getHeight() - BAR_HEIGHT - metrics.getDescent()) / 2;
       
       // draws the text
       g2.setColor(TEXT_COLOR);
       g2.drawString(message, x, y);
       
       // goes to the position of the progress bar
       y += metrics.getDescent();
       
       // computes the size of the progress indicator
       int w = (int) (BAR_WIDTH * ((float) progress / 100.0f));
       int h = BAR_HEIGHT;
       
       // draws the content of the progress bar
       Paint paint = g2.getPaint();
       
       // bar"s background
       Paint gradient = new GradientPaint(x, y, GRADIENT_COLOR1,
               x, y + h, GRADIENT_COLOR2);
       g2.setPaint(gradient);
       g2.fillRect(x, y, BAR_WIDTH, BAR_HEIGHT);
       
       // actual progress
       gradient = new LinearGradientPaint(x, y, x, y + h,
               GRADIENT_FRACTIONS, GRADIENT_COLORS);
       g2.setPaint(gradient);
       g2.fillRect(x, y, w, h);
       
       g2.setPaint(paint);
       
       // draws the progress bar border
       g2.drawRect(x, y, BAR_WIDTH, BAR_HEIGHT);
       
       g2.setComposite(composite);
   }

}


      </source>
   
  
 
  



Glasspane Painting

   <source lang="java">

/*

* Copyright (c) 2007, Romain Guy
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
*   * Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*   * Redistributions in binary form must reproduce the above
*     copyright notice, this list of conditions and the following
*     disclaimer in the documentation and/or other materials provided
*     with the distribution.
*   * Neither the name of the TimingFramework project nor the names of its
*     contributors may be used to endorse or promote products derived
*     from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/**

*
* @author Romain Guy
*/

import java.awt.AlphaComposite;

import java.awt.Color; import java.awt.ruposite; import java.awt.Font; import java.awt.FontMetrics; import java.awt.GradientPaint; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.LinearGradientPaint; import java.awt.Paint; import java.awt.Rectangle; import java.awt.RenderingHints; import javax.swing.JComponent; public class GlassPanePainting extends javax.swing.JFrame {

   private static final int MAX_DELAY = 300;
   
   private ProgressGlassPane glassPane;
   
   public GlassPanePainting() {
       initComponents();
       setGlassPane(glassPane = new ProgressGlassPane());
   }
   
   /** This method is called from within the constructor to
    * initialize the form.
    * WARNING: Do NOT modify this code. The content of this method is
    * always regenerated by the Form Editor.
    */
   // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
   private void initComponents() {
       javax.swing.JButton buttonDownload;
       javax.swing.JLabel jLabel1;
       javax.swing.JScrollPane jScrollPane1;
       jLabel1 = new javax.swing.JLabel();
       buttonDownload = new javax.swing.JButton();
       jScrollPane1 = new javax.swing.JScrollPane();
       filesTable = new javax.swing.JTable();
       setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
       setTitle("Glass Pane Painting");
       setResizable(false);
       jLabel1.setText("Pick a file for download");
       buttonDownload.setText("Start Download");
       buttonDownload.addActionListener(new java.awt.event.ActionListener() {
           public void actionPerformed(java.awt.event.ActionEvent evt) {
               buttonDownloadActionPerformed(evt);
           }
       });
       filesTable.setModel(new javax.swing.table.DefaultTableModel(
           new Object [][] {
               {"aerith.png", "/www/progx/images/", "PNG", "5/17/2006"},
               {"blog.html", "/www/progx", "HTML", "3/1/2006"},
               {"index.html", "/www/progx", "HTML", "9/12/2006"},
               {"pictures.zip", "/www/progx", "ZIP", "10/8/2006"}
           },
           new String [] {
               "Name", "Path", "Type", "Date"
           }
       ));
       jScrollPane1.setViewportView(filesTable);
       org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane());
       getContentPane().setLayout(layout);
       layout.setHorizontalGroup(
           layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
           .add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup()
               .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
                   .add(layout.createSequentialGroup()
                       .addContainerGap()
                       .add(buttonDownload))
                   .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                       .add(layout.createSequentialGroup()
                           .addContainerGap()
                           .add(jLabel1))
                       .add(layout.createSequentialGroup()
                           .addContainerGap()
                           .add(jScrollPane1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 513, Short.MAX_VALUE))))
               .addContainerGap())
       );
       layout.setVerticalGroup(
           layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
           .add(layout.createSequentialGroup()
               .add(20, 20, 20)
               .add(jLabel1)
               .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
               .add(jScrollPane1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 275, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
               .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
               .add(buttonDownload)
               .addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
       );
       java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
       setBounds((screenSize.width-553)/2, (screenSize.height-394)/2, 553, 394);
   }// </editor-fold>//GEN-END:initComponents
   private void buttonDownloadActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonDownloadActionPerformed
       getGlassPane().setVisible(true);
       startDownloadThread();
   }//GEN-LAST:event_buttonDownloadActionPerformed
   
   private void startDownloadThread() {
       Thread downloader = new Thread(new Runnable() {
           public void run() {
               int i = 0;
               do {
                   try {
                       Thread.sleep(30 + (int) (Math.random() * MAX_DELAY));
                   } catch (InterruptedException ex) {
                       // who cares here?
                   }
                   i += (int) (Math.random() * 5);
                   glassPane.setProgress(i);
               } while (i < 100);
               glassPane.setVisible(false);
               glassPane.setProgress(0);
           }
       });
       downloader.start();
   }
   
   /**
    * @param args the command line arguments
    */
   public static void main(String args[]) {
       java.awt.EventQueue.invokeLater(new Runnable() {
           public void run() {
               new GlassPanePainting().setVisible(true);
           }
       });
   }
   
   // Variables declaration - do not modify//GEN-BEGIN:variables
   private javax.swing.JTable filesTable;
   // End of variables declaration//GEN-END:variables
   

} /*

* Copyright (c) 2007, Romain Guy
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
*   * Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*   * Redistributions in binary form must reproduce the above
*     copyright notice, this list of conditions and the following
*     disclaimer in the documentation and/or other materials provided
*     with the distribution.
*   * Neither the name of the TimingFramework project nor the names of its
*     contributors may be used to endorse or promote products derived
*     from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/**

*
* @author Romain Guy
*/

class ProgressGlassPane extends JComponent {

   private static final int BAR_WIDTH = 200;
   private static final int BAR_HEIGHT = 10;
   
   private static final Color TEXT_COLOR = new Color(0x333333);
   private static final Color BORDER_COLOR = new Color(0x333333);
   
   private static final float[] GRADIENT_FRACTIONS = new float[] {
       0.0f, 0.499f, 0.5f, 1.0f
   };
   private static final Color[] GRADIENT_COLORS = new Color[] {
       Color.GRAY, Color.DARK_GRAY, Color.BLACK, Color.GRAY
   };
   private static final Color GRADIENT_COLOR2 = Color.WHITE;
   private static final Color GRADIENT_COLOR1 = Color.GRAY;
   private String message = "Downloading file...";
   private int progress = 0;
   
   public ProgressGlassPane() {
       setBackground(Color.WHITE);
       setFont(new Font("Default", Font.BOLD, 16));
   }
   public int getProgress() {
       return progress;
   }
   public void setProgress(int progress) {
       int oldProgress = this.progress;
       this.progress = progress;
       
       // computes the damaged area
       FontMetrics metrics = getGraphics().getFontMetrics(getFont()); 
       int w = (int) (BAR_WIDTH * ((float) oldProgress / 100.0f));
       int x = w + (getWidth() - BAR_WIDTH) / 2;
       int y = (getHeight() - BAR_HEIGHT) / 2;
       y += metrics.getDescent() / 2;
       
       w = (int) (BAR_WIDTH * ((float) progress / 100.0f)) - w;
       int h = BAR_HEIGHT;
       
       repaint(x, y, w, h);
   }
   
   @Override
   protected void paintComponent(Graphics g) {
       // enables anti-aliasing
       Graphics2D g2 = (Graphics2D) g;
       g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
               RenderingHints.VALUE_ANTIALIAS_ON);
       
       // gets the current clipping area
       Rectangle clip = g.getClipBounds();
       
       // sets a 65% translucent composite
       AlphaComposite alpha = AlphaComposite.SrcOver.derive(0.65f);
       Composite composite = g2.getComposite();
       g2.setComposite(alpha);
       
       // fills the background
       g2.setColor(getBackground());
       g2.fillRect(clip.x, clip.y, clip.width, clip.height);
       
       // centers the progress bar on screen
       FontMetrics metrics = g.getFontMetrics();        
       int x = (getWidth() - BAR_WIDTH) / 2;
       int y = (getHeight() - BAR_HEIGHT - metrics.getDescent()) / 2;
       
       // draws the text
       g2.setColor(TEXT_COLOR);
       g2.drawString(message, x, y);
       
       // goes to the position of the progress bar
       y += metrics.getDescent();
       
       // computes the size of the progress indicator
       int w = (int) (BAR_WIDTH * ((float) progress / 100.0f));
       int h = BAR_HEIGHT;
       
       // draws the content of the progress bar
       Paint paint = g2.getPaint();
       
       // bar"s background
       Paint gradient = new GradientPaint(x, y, GRADIENT_COLOR1,
               x, y + h, GRADIENT_COLOR2);
       g2.setPaint(gradient);
       g2.fillRect(x, y, BAR_WIDTH, BAR_HEIGHT);
       
       // actual progress
       gradient = new LinearGradientPaint(x, y, x, y + h,
               GRADIENT_FRACTIONS, GRADIENT_COLORS);
       g2.setPaint(gradient);
       g2.fillRect(x, y, w, h);
       
       g2.setPaint(paint);
       
       // draws the progress bar border
       g2.drawRect(x, y, BAR_WIDTH, BAR_HEIGHT);
       
       g2.setComposite(composite);
   }

}


      </source>