/*
* 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.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;
import java.util.HashMap;
import java.util.Map;
import javax.swing.UIManager;
import javax.swing.border.Border;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import java.awt.image.ColorModel;
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.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;
import java.util.Map;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
/**
*
* @author Romain Guy <romain.guy@mac.com>
*/
public class TextHighlightingDemo extends JFrame {
private VistaSearchDialog dialog;
public TextHighlightingDemo() {
super("Text Highlighting");
add(new DummyPanel());
JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEADING));
JButton button = new JButton("Show Dialog");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
dialog = new VistaSearchDialog(TextHighlightingDemo.this);
installInLayeredPane(dialog);
dialog.setVisible(true);
}
});
panel.add(button);
add(panel, BorderLayout.SOUTH);
pack();
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
private void installInLayeredPane(JComponent component) {
JLayeredPane layeredPane = getRootPane().getLayeredPane();
layeredPane.add(component, JLayeredPane.PALETTE_LAYER, 20);
Dimension size = component.getPreferredSize();
component.setSize(size);
component.setLocation((getWidth() - size.width) / 2,
(getHeight() - size.height) / 2);
component.revalidate();
component.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new TextHighlightingDemo().setVisible(true);
}
});
}
}
/*
* 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.
*/
class VistaSearchDialog extends JComponent {
private static final int BLUR_SIZE = 7;
private BufferedImage image;
private float alpha = 0.0f;
public VistaSearchDialog(JFrame frame) {
Container contentPane = frame.getRootPane();
image = GraphicsUtilities.createCompatibleTranslucentImage(contentPane.getWidth() +
2 * (int) BLUR_SIZE,
contentPane.getHeight() +
2 * (int) BLUR_SIZE);
Graphics2D g2 = image.createGraphics();
g2.translate(BLUR_SIZE, BLUR_SIZE);
contentPane.paint(g2);
g2.translate(-BLUR_SIZE, -BLUR_SIZE);
g2.dispose();
// 1.5 second vs 0.3 second
// long start = System.currentTimeMillis();
image = changeImageWidth(image, image.getWidth() / 2);
ConvolveOp gaussianFilter = getGaussianBlurFilter(BLUR_SIZE, true);
image = gaussianFilter.filter(image, null);
gaussianFilter = getGaussianBlurFilter(BLUR_SIZE, false);
image = gaussianFilter.filter(image, null);
ColorTintFilter colorMixFilter = new ColorTintFilter(Color.WHITE, 0.4f);
image = colorMixFilter.filter(image, null);
image = changeImageWidth(image, image.getWidth() * 2);
// System.out.println("time = " +
// ((System.currentTimeMillis() - start) / 1000.0f));
setBorder(new DropShadowBorder(Color.BLACK, 0, 11, .2f, 16,
false, true, true, true));
setLayout(new BorderLayout());
initComponents();
}
public static BufferedImage changeImageWidth(BufferedImage image, int width) {
float ratio = (float) image.getWidth() / (float) image.getHeight();
int height = (int) (width / ratio);
BufferedImage temp = new BufferedImage(width, height,
image.getType());
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;
}
public static ConvolveOp getGaussianBlurFilter(int radius,
boolean horizontal) {
if (radius < 1) {
throw new IllegalArgumentException("Radius must be >= 1");
}
int size = radius * 2 + 1;
float[] data = new float[size];
float sigma = radius / 3.0f;
float twoSigmaSquare = 2.0f * sigma * sigma;
float sigmaRoot = (float) Math.sqrt(twoSigmaSquare * Math.PI);
float total = 0.0f;
for (int i = -radius; i <= radius; i++) {
float distance = i * i;
int index = i + radius;
data[index] = (float) Math.exp(-distance / twoSigmaSquare) / sigmaRoot;
total += data[index];
}
for (int i = 0; i < data.length; i++) {
data[i] /= total;
}
Kernel kernel = null;
if (horizontal) {
kernel = new Kernel(size, 1, data);
} else {
kernel = new Kernel(1, size, data);
}
return new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null);
}
private void initComponents() {
TitleBar titleBar =
new TitleBar("Search in this Message");
add(titleBar, BorderLayout.NORTH);
SearchPanel contentPane = new SearchPanel();
contentPane.setOpaque(false);
contentPane.setBorder(BorderFactory.createEmptyBorder(16, 2, 16, 2));
add(contentPane);
}
@Override
public boolean isOpaque() {
return false;
}
@Override
protected void paintComponent(Graphics g) {
setupGraphics((Graphics2D) g);
Point location = getLocation();
location.x = (int) (-location.x - BLUR_SIZE);
location.y = (int) (-location.y - BLUR_SIZE);
Insets insets = getInsets();
Shape oldClip = g.getClip();
g.setClip(insets.left, insets.top,
getWidth() - insets.left - insets.right,
getHeight() - insets.top - insets.bottom);
g.drawImage(image, location.x, location.y, null);
g.setClip(oldClip);
}
public float getAlpha() {
return alpha;
}
public void setAlpha(float alpha) {
this.alpha = alpha;
repaint();
}
private static void setupGraphics(Graphics2D g2) {
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
Toolkit tk = Toolkit.getDefaultToolkit();
Map desktopHints = (Map) (tk.getDesktopProperty("awt.font.desktophints"));
if (desktopHints != null) {
g2.addRenderingHints(desktopHints);
}
}
private class TitleBar extends JComponent {
private String title;
private TitleBar(String title) {
this.title = title;
setName("vistaTitleBar");
setFont(new Font("Dialog", Font.BOLD, 12));
setLayout(new GridBagLayout());
JButton button = new JButton();
button.setMargin(new Insets(0, 0, 0, 0));
button.setBorder(null);
button.setIconTextGap(0);
button.setVerticalAlignment(SwingConstants.TOP);
button.setContentAreaFilled(false);
button.setBorderPainted(false);
button.setFocusPainted(false);
button.setIcon(new ImageIcon(getClass().getResource("close-title-bar.png")));
button.setRolloverIcon(new ImageIcon(getClass().getResource("close-title-bar-rollover.png")));
button.setOpaque(false);
button.setName("vistaCloseButton");
add(Box.createVerticalStrut(24),
new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0,
GridBagConstraints.LINE_START,
GridBagConstraints.HORIZONTAL,
new Insets(0, 0, 0, 0), 0, 0));
add(button, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0,
GridBagConstraints.FIRST_LINE_END,
GridBagConstraints.VERTICAL,
new Insets(0, 0, 0, 0), 0, 0));
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
VistaSearchDialog.this.setVisible(false);
}
});
Locator locator = new Locator();
addMouseListener(locator);
addMouseMotionListener(locator);
}
@Override
public boolean isOpaque() {
return false;
}
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
setupGraphics(g2);
Paint oldPaint = g2.getPaint();
float rgb[] = new Color(0xe9efff).getRGBColorComponents(null);
g2.setPaint(new GradientPaint(0.0f, 0.0f,
new Color(rgb[0], rgb[1], rgb[2], 0.2f * getAlpha()),
0.0f, getHeight(),
new Color(rgb[0], rgb[1], rgb[2], 0.8f * getAlpha())));
g2.fillRect(0, 0, getWidth(), getHeight());
drawText(g2, 3, 0.8f);
g2.setPaint(oldPaint);
g2.setColor(new Color(rgb[0], rgb[1], rgb[2], 0.6f * getAlpha()));
g2.drawLine(0, getHeight() - 1, getWidth(), getHeight() - 1);
g2.drawLine(0, getHeight() - 2, getWidth(), getHeight() - 2);
}
private void drawText(Graphics2D g2, int size, float opacity) {
Composite oldComposite = g2.getComposite();
float preAlpha = 1.0f;
if (oldComposite instanceof AlphaComposite &&
((AlphaComposite) oldComposite).getRule() == AlphaComposite.SRC_OVER) {
preAlpha = ((AlphaComposite) oldComposite).getAlpha();
}
g2.setFont(getFont());
FontMetrics metrics = g2.getFontMetrics();
int ascent = metrics.getAscent();
int heightDiff = (metrics.getHeight() - ascent) / 2;
g2.setColor(Color.BLACK);
double tx = 2.0;
double ty = 2.0 + heightDiff - size;
g2.translate(tx, ty);
for (int i = -size; i <= size; i++) {
for (int j = -size; j <= size; j++) {
double distance = i * i + j * j;
float alpha = opacity;
if (distance > 0.0d) {
alpha = (float) (1.0f / ((distance * size) * opacity));
}
alpha *= preAlpha;
if (alpha > 1.0f) {
alpha = 1.0f;
}
g2.setComposite(AlphaComposite.SrcOver.derive(alpha));
g2.drawString(title, i + size, j + size + ascent);
}
}
g2.setComposite(oldComposite);
g2.setColor(Color.WHITE);
g2.drawString(title, size, size + ascent);
g2.translate(-tx, -ty);
}
}
private class Locator extends MouseAdapter {
private Point startPoint;
@Override
public void mousePressed(MouseEvent e) {
startPoint = e.getPoint();
SwingUtilities.convertPointToScreen(startPoint, (Component) e.getSource());
}
@Override
public void mouseReleased(MouseEvent e) {
VistaSearchDialog.this.setCursor(Cursor.getDefaultCursor());
}
@Override
public void mouseDragged(MouseEvent e) {
Point point = e.getPoint();
SwingUtilities.convertPointToScreen(point, (Component) e.getSource());
int distance_x = point.x - startPoint.x;
int distance_y = point.y - startPoint.y;
VistaSearchDialog.this.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
Point location = VistaSearchDialog.this.getLocation();
Point oldLocation = (Point) location.clone();
location.x += distance_x;
location.y += distance_y;
VistaSearchDialog.this.setLocation(location);
Rectangle clip = new Rectangle(oldLocation.x, oldLocation.y,
VistaSearchDialog.this.getWidth(),
VistaSearchDialog.this.getHeight());
clip.intersects(new Rectangle(location.x, location.y,
VistaSearchDialog.this.getWidth(),
VistaSearchDialog.this.getHeight()));
VistaSearchDialog.this.getParent().repaint(clip.x, clip.y,
clip.width, clip.height);
startPoint = point;
}
}
}
/*
* 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 SearchPanel extends javax.swing.JPanel {
/** Creates new form SearchPanel */
public SearchPanel() {
initComponents();
}
/** 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() {
java.awt.GridBagConstraints gridBagConstraints;
jRadioButton2 = new javax.swing.JRadioButton();
jLabel1 = new javax.swing.JLabel();
jTextField1 = new javax.swing.JTextField();
jButton1 = new javax.swing.JButton();
jCheckBox1 = new javax.swing.JCheckBox();
jLabel2 = new javax.swing.JLabel();
jRadioButton1 = new javax.swing.JRadioButton();
jButton2 = new javax.swing.JButton();
jCheckBox2 = new javax.swing.JCheckBox();
jRadioButton3 = new javax.swing.JRadioButton();
jRadioButton2.setText("jRadioButton2");
jRadioButton2.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
jRadioButton2.setMargin(new java.awt.Insets(0, 0, 0, 0));
jLabel1.setText("Find what:");
jTextField1.setColumns(15);
jButton1.setText("Search Next");
jButton1.setOpaque(false);
jCheckBox1.setText("Match case");
jCheckBox1.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
jCheckBox1.setMargin(new java.awt.Insets(0, 0, 0, 0));
jCheckBox1.setOpaque(false);
jLabel2.setText("Direction:");
jRadioButton1.setSelected(true);
jRadioButton1.setText("Up");
jRadioButton1.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
jRadioButton1.setMargin(new java.awt.Insets(0, 0, 0, 0));
jRadioButton1.setOpaque(false);
jButton2.setText("Cancel");
jButton2.setOpaque(false);
jButton2.setPreferredSize(new java.awt.Dimension(91, 23));
jCheckBox2.setText("Wrap");
jCheckBox2.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
jCheckBox2.setMargin(new java.awt.Insets(0, 0, 0, 0));
jCheckBox2.setOpaque(false);
jRadioButton3.setText("Down");
jRadioButton3.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
jRadioButton3.setMargin(new java.awt.Insets(0, 0, 0, 0));
jRadioButton3.setOpaque(false);
org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(layout.createSequentialGroup()
.addContainerGap()
.add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(layout.createSequentialGroup()
.add(jLabel1)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(jTextField1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 279, Short.MAX_VALUE)
.addContainerGap())
.add(layout.createSequentialGroup()
.add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(layout.createSequentialGroup()
.add(jCheckBox1)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 26, Short.MAX_VALUE)
.add(jLabel2))
.add(jCheckBox2))
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(jRadioButton3)
.add(jRadioButton1))
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(org.jdesktop.layout.GroupLayout.TRAILING, jButton2, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 75, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.add(org.jdesktop.layout.GroupLayout.TRAILING, jButton1))
.add(23, 23, 23))))
);
layout.linkSize(new java.awt.Component[] {jButton1, jButton2}, org.jdesktop.layout.GroupLayout.HORIZONTAL);
layout.setVerticalGroup(
layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(layout.createSequentialGroup()
.addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.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))
.add(8, 8, 8)
.add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
.add(jButton1)
.add(jRadioButton1)
.add(jLabel2)
.add(jCheckBox1))
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
.add(jButton2, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 29, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.add(jRadioButton3)
.add(jCheckBox2))
.addContainerGap())
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton jButton1;
private javax.swing.JButton jButton2;
private javax.swing.JCheckBox jCheckBox1;
private javax.swing.JCheckBox jCheckBox2;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JRadioButton jRadioButton1;
private javax.swing.JRadioButton jRadioButton2;
private javax.swing.JRadioButton jRadioButton3;
private javax.swing.JTextField jTextField1;
// 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 <romain.guy@mac.com>
*/
class DummyPanel extends javax.swing.JPanel {
/** Creates new form DummyPanel */
public DummyPanel() {
initComponents();
}
/** 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() {
jLabel1 = new javax.swing.JLabel();
jTextField1 = new javax.swing.JTextField();
jScrollPane1 = new javax.swing.JScrollPane();
jTable1 = new javax.swing.JTable();
jScrollPane2 = new javax.swing.JScrollPane();
jTree1 = new javax.swing.JTree();
jScrollPane3 = new javax.swing.JScrollPane();
jList1 = new javax.swing.JList();
jScrollPane4 = new javax.swing.JScrollPane();
jList2 = new javax.swing.JList();
jLabel1.setText("Filter:");
jTable1.setModel(new javax.swing.table.DefaultTableModel(
new Object [][] {
{null, null, null, null},
{null, null, null, null},
{null, null, null, null},
{null, null, null, null}
},
new String [] {
"Title 1", "Title 2", "Title 3", "Title 4"
}
));
jScrollPane1.setViewportView(jTable1);
jScrollPane2.setViewportView(jTree1);
jList1.setModel(new javax.swing.AbstractListModel() {
String[] strings = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
public int getSize() { return strings.length; }
public Object getElementAt(int i) { return strings[i]; }
});
jScrollPane3.setViewportView(jList1);
jList2.setModel(new javax.swing.AbstractListModel() {
String[] strings = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
public int getSize() { return strings.length; }
public Object getElementAt(int i) { return strings[i]; }
});
jScrollPane4.setViewportView(jList2);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addGroup(layout.createSequentialGroup()
.addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 181, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
.addComponent(jScrollPane3, javax.swing.GroupLayout.PREFERRED_SIZE, 165, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane4, javax.swing.GroupLayout.DEFAULT_SIZE, 211, Short.MAX_VALUE))
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 386, Short.MAX_VALUE)))
.addGroup(layout.createSequentialGroup()
.addComponent(jLabel1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jTextField1, javax.swing.GroupLayout.DEFAULT_SIZE, 531, Short.MAX_VALUE)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel1)
.addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 96, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane4, javax.swing.GroupLayout.DEFAULT_SIZE, 280, Short.MAX_VALUE)
.addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 280, Short.MAX_VALUE)))
.addComponent(jScrollPane2))
.addContainerGap())
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JLabel jLabel1;
private javax.swing.JList jList1;
private javax.swing.JList jList2;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JScrollPane jScrollPane2;
private javax.swing.JScrollPane jScrollPane3;
private javax.swing.JScrollPane jScrollPane4;
private javax.swing.JTable jTable1;
private javax.swing.JTextField jTextField1;
private javax.swing.JTree jTree1;
// End of variables declaration//GEN-END:variables
}
/*
* $Id: GraphicsUtilities.java,v 1.1 2007/01/16 18:31:51 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.com>
* 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.
*/
/**
* <p><code>GraphicsUtilities</code> contains a set of tools to perform
* common graphics operations easily. These operations are divided into
* several themes, listed below.</p>
* <h2>Compatible Images</h2>
* <p>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.</p>
* <h2>Creating Thumbnails</h2>
* <p>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.</p>
* <p>All these methodes are both faster than
* {@link java.awt.Image#getScaledInstance(int, int, int)} and produce
* better-looking results than the various <code>drawImage()</code> methods
* in {@link java.awt.Graphics}, which can be used for image scaling.</p>
* <h2>Image Manipulation</h2>
* <p>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.</p>
*
* @author Romain Guy <romain.guy@mac.com>
*/
class GraphicsUtilities {
private GraphicsUtilities() {
}
// Returns the graphics configuration for the primary screen
private static GraphicsConfiguration getGraphicsConfiguration() {
return GraphicsEnvironment.getLocalGraphicsEnvironment().
getDefaultScreenDevice().getDefaultConfiguration();
}
/**
* <p>Returns a new <code>BufferedImage</code> 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.</p>
*
* @param image the reference image from which the color model of the new
* image is obtained
* @return a new <code>BufferedImage</code>, compatible with the color model
* of <code>image</code>
*/
public static BufferedImage createColorModelCompatibleImage(BufferedImage image) {
ColorModel cm = image.getColorModel();
return new BufferedImage(cm,
cm.createCompatibleWritableRaster(image.getWidth(),
image.getHeight()),
cm.isAlphaPremultiplied(), null);
}
/**
* <p>Returns a new compatible image with the same width, height and
* transparency as the image specified as a parameter.</p>
*
* @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 <code>BufferedImage</code> with the same
* dimension and transparency as <code>image</code>
*/
public static BufferedImage createCompatibleImage(BufferedImage image) {
return createCompatibleImage(image, image.getWidth(), image.getHeight());
}
/**
* <p>Returns a new compatible image of the specified width and height, and
* the same transparency setting as the image specified as a parameter.</p>
*
* @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 <code>BufferedImage</code> with the same
* transparency as <code>image</code> and the specified dimension
*/
public static BufferedImage createCompatibleImage(BufferedImage image,
int width, int height) {
return getGraphicsConfiguration().createCompatibleImage(width, height,
image.getTransparency());
}
/**
* <p>Returns a new opaque compatible image of the specified width and
* height.</p>
*
* @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 <code>BufferedImage</code> of the
* specified width and height
*/
public static BufferedImage createCompatibleImage(int width, int height) {
return getGraphicsConfiguration().createCompatibleImage(width, height);
}
/**
* <p>Returns a new translucent compatible image of the specified width
* and height.</p>
*
* @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 <code>BufferedImage</code> of the
* specified width and height
*/
public static BufferedImage createCompatibleTranslucentImage(int width,
int height) {
return getGraphicsConfiguration().createCompatibleImage(width, height,
Transparency.TRANSLUCENT);
}
/**
* <p>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.</p>
*
* @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 <code>BufferedImage</code> 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);
}
/**
* <p>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.</p>
*
* @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 <code>image</code>
*/
public static BufferedImage toCompatibleImage(BufferedImage 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;
}
/**
* <p>Returns a thumbnail of a source image. <code>newSize</code> 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.</p>
* <p>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.</p>
*
* @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 <code>BufferedImage</code> containing a
* thumbnail of <code>image</code>
* @throws IllegalArgumentException if <code>newSize</code> is larger than
* the largest dimension of <code>image</code> 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;
}
/**
* <p>Returns a thumbnail of a source image.</p>
* <p>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.</p>
*
* @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 <code>BufferedImage</code> containing a
* thumbnail of <code>image</code>
* @throws IllegalArgumentException if <code>newWidth</code> is larger than
* the width of <code>image</code> or if code>newHeight</code> is larger
* than the height of <code>image</code> 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;
}
/**
* <p>Returns a thumbnail of a source image. <code>newSize</code> 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.</p>
* <p>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.</p>
*
* @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 <code>BufferedImage</code> containing a
* thumbnail of <code>image</code>
* @throws IllegalArgumentException if <code>newSize</code> is larger than
* the largest dimension of <code>image</code> or <= 0
*/
public static BufferedImage createThumbnail(BufferedImage image,
int newSize) {
int width = image.getWidth();
int height = image.getHeight();
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;
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);
}
BufferedImage temp = createCompatibleImage(image, width, height);
Graphics2D g2 = temp.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2.drawImage(thumb, 0, 0, temp.getWidth(), temp.getHeight(), null);
g2.dispose();
thumb = temp;
} while (newSize != (isWidthGreater ? width : height));
return thumb;
}
/**
* <p>Returns a thumbnail of a source image.</p>
* <p>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.</p>
*
* @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 <code>BufferedImage</code> containing a
* thumbnail of <code>image</code>
* @throws IllegalArgumentException if <code>newWidth</code> is larger than
* the width of <code>image</code> or if code>newHeight</code> is larger
* than the height of <code>image or if one the dimensions is not > 0</code>
*/
public static BufferedImage createThumbnail(BufferedImage image,
int newWidth, int newHeight) {
int width = image.getWidth();
int height = image.getHeight();
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;
do {
if (width > newWidth) {
width /= 2;
if (width < newWidth) {
width = newWidth;
}
}
if (height > newHeight) {
height /= 2;
if (height < newHeight) {
height = newHeight;
}
}
BufferedImage temp = createCompatibleImage(image, width, height);
Graphics2D g2 = temp.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2.drawImage(thumb, 0, 0, temp.getWidth(), temp.getHeight(), null);
g2.dispose();
thumb = temp;
} while (width != newWidth || height != newHeight);
return thumb;
}
/**
* <p>Returns an array of pixels, stored as integers, from a
* <code>BufferedImage</code>. 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 <code>BufferedImage.TYPE_INT_ARGB</code>
* and <code>BufferedImage.TYPE_INT_RGB</code> will unmanage the image.</p>
*
* @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 <code>pixels</code> if non-null, a new array of integers
* otherwise
* @throws IllegalArgumentException is <code>pixels</code> 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);
}
/**
* <p>Writes a rectangular area of pixels in the destination
* <code>BufferedImage</code>. Calling this method on
* an image of type different from <code>BufferedImage.TYPE_INT_ARGB</code>
* and <code>BufferedImage.TYPE_INT_RGB</code> will unmanage the image.</p>
*
* @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 <code>pixels</code> 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);
}
}
}
/*
* $Id: AbstractFilter.java,v 1.1 2007/01/16 18:31:50 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.com>
* 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.
*/
/**
* <p>Provides an abstract implementation of the <code>BufferedImageOp</code>
* interface. This class can be used to created new image filters based
* on <code>BufferedImageOp</code>.</p>
*
* @author Romain Guy <romain.guy@mac.com>
*/
abstract class AbstractFilter implements BufferedImageOp {
public abstract BufferedImage filter(BufferedImage src, BufferedImage dest);
/**
* {@inheritDoc}
*/
public Rectangle2D getBounds2D(BufferedImage src) {
return new Rectangle(0, 0, src.getWidth(), src.getHeight());
}
/**
* {@inheritDoc}
*/
public BufferedImage createCompatibleDestImage(BufferedImage src,
ColorModel destCM) {
if (destCM == null) {
destCM = src.getColorModel();
}
return new BufferedImage(destCM,
destCM.createCompatibleWritableRaster(
src.getWidth(), src.getHeight()),
destCM.isAlphaPremultiplied(), null);
}
/**
* {@inheritDoc}
*/
public Point2D getPoint2D(Point2D srcPt, Point2D dstPt) {
return (Point2D) srcPt.clone();
}
/**
* {@inheritDoc}
*/
public RenderingHints getRenderingHints() {
return null;
}
}
/*
* $Id: ColorTintFilter.java,v 1.2 2007/01/28 01:45:47 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.com>
* 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.
*/
/**
* <p>A color tint filter can be used to mix a solid color to an image. The
* result is an image tinted by the specified color. The force of the effect
* can be controlled with the <code>mixValue</code>, a number between 0.0 and
* 1.0 that can be seen as the percentage of the mix (0.0 does not affect the
* source image and 1.0 replaces all the pixels by the solid color).</p>
* <p>The color of the pixels in the resulting image is computed as follows:</p>
* <pre>
* cR = cS * (1 - mixValue) + cM * mixValue
* </pre>
* <p>Definition of the parameters:</p>
* <ul>
* <li><code>cR</code>: color of the resulting pixel</li>
* <li><code>cS</code>: color of the source pixel</li>
* <li><code>cM</code>: the solid color to mix with the source image</li>
* <li><code>mixValue</code>: strength of the mix, a value between 0.0 and 1.0</li>
* </ul>
*
* @author Romain Guy <romain.guy@mac.com>
*/
class ColorTintFilter extends AbstractFilter {
private final Color mixColor;
private final float mixValue;
private int[] preMultipliedRed;
private int[] preMultipliedGreen;
private int[] preMultipliedBlue;
/**
* <p>Creates a new color mixer filter. The specified color will be used
* to tint the source image, with a mixing strength defined by
* <code>mixValue</code>.</p>
*
* @param mixColor the solid color to mix with the source image
* @param mixValue the strength of the mix, between 0.0 and 1.0; if the
* specified value lies outside this range, it is clamped
* @throws IllegalArgumentException if <code>mixColor</code> is null
*/
public ColorTintFilter(Color mixColor, float mixValue) {
if (mixColor == null) {
throw new IllegalArgumentException("mixColor cannot be null");
}
this.mixColor = mixColor;
if (mixValue < 0.0f) {
mixValue = 0.0f;
} else if (mixValue > 1.0f) {
mixValue = 1.0f;
}
this.mixValue = mixValue;
int mix_r = (int) (mixColor.getRed() * mixValue);
int mix_g = (int) (mixColor.getGreen() * mixValue);
int mix_b = (int) (mixColor.getBlue() * mixValue);
// Since we use only lookup tables to apply the filter, this filter
// could be implemented as a LookupOp.
float factor = 1.0f - mixValue;
preMultipliedRed = new int[256];
preMultipliedGreen = new int[256];
preMultipliedBlue = new int[256];
for (int i = 0; i < 256; i++) {
int value = (int) (i * factor);
preMultipliedRed[i] = value + mix_r;
preMultipliedGreen[i] = value + mix_g;
preMultipliedBlue[i] = value + mix_b;
}
}
/**
* <p>Returns the mix value of this filter.</p>
*
* @return the mix value, between 0.0 and 1.0
*/
public float getMixValue() {
return mixValue;
}
/**
* <p>Returns the solid mix color of this filter.</p>
*
* @return the solid color used for mixing
*/
public Color getMixColor() {
return mixColor;
}
/**
* {@inheritDoc}
*/
@Override
public BufferedImage filter(BufferedImage src, BufferedImage dst) {
if (dst == null) {
dst = createCompatibleDestImage(src, null);
}
int width = src.getWidth();
int height = src.getHeight();
int[] pixels = new int[width * height];
GraphicsUtilities.getPixels(src, 0, 0, width, height, pixels);
mixColor(pixels);
GraphicsUtilities.setPixels(dst, 0, 0, width, height, pixels);
return dst;
}
private void mixColor(int[] pixels) {
for (int i = 0; i < pixels.length; i++) {
int argb = pixels[i];
pixels[i] = (argb & 0xFF000000) |
preMultipliedRed[(argb >> 16) & 0xFF] << 16 |
preMultipliedGreen[(argb >> 8) & 0xFF] << 8 |
preMultipliedBlue[argb & 0xFF];
}
}
}
/*
* $Id: DropShadowBorder.java,v 1.1 2007/01/16 18:31:49 gfx Exp $
*
* Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
* Santa Clara, California 95054, U.S.A. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* Implements a DropShadow for components. In general, the DropShadowBorder will
* work with any rectangular components that do not have a default border installed
* as part of the look and feel, or otherwise. For example, DropShadowBorder works
* wonderfully with JPanel, but horribly with JComboBox.
*
* @author rbair
*/
class DropShadowBorder implements Border {
private static enum Position {TOP, TOP_LEFT, LEFT, BOTTOM_LEFT,
BOTTOM, BOTTOM_RIGHT, RIGHT, TOP_RIGHT};
private static final Map<Integer,Map<Position,BufferedImage>> CACHE
= new HashMap<Integer,Map<Position,BufferedImage>>();
private final Color lineColor;
private final int lineWidth;
private final int shadowSize;
private final float shadowOpacity;
private final int cornerSize;
private final boolean showTopShadow;
private final boolean showLeftShadow;
private final boolean showBottomShadow;
private final boolean showRightShadow;
public DropShadowBorder() {
this(UIManager.getColor("Control"), 1, 5);
}
public DropShadowBorder(Color lineColor, int lineWidth, int shadowSize) {
this(lineColor, lineWidth, shadowSize, .5f, 12, false, false, true, true);
}
public DropShadowBorder(Color lineColor, int lineWidth, boolean showLeftShadow) {
this(lineColor, lineWidth, 5, .5f, 12, false, showLeftShadow, true, true);
}
public DropShadowBorder(Color lineColor, int lineWidth, int shadowSize,
float shadowOpacity, int cornerSize, boolean showTopShadow,
boolean showLeftShadow, boolean showBottomShadow, boolean showRightShadow) {
this.lineColor = lineColor;
this.lineWidth = lineWidth;
this.shadowSize = shadowSize;
this.shadowOpacity = shadowOpacity;
this.cornerSize = cornerSize;
this.showTopShadow = showTopShadow;
this.showLeftShadow = showLeftShadow;
this.showBottomShadow = showBottomShadow;
this.showRightShadow = showRightShadow;
}
/**
* @inheritDoc
*/
public void paintBorder(Component c, Graphics graphics, int x, int y, int width, int height) {
/*
* 1) Get images for this border
* 2) Paint the images for each side of the border that should be painted
*/
Map<Position,BufferedImage> images = getImages((Graphics2D)graphics);
//compute the edges of the component -- not including the border
// Insets borderInsets = getBorderInsets(c);
// int leftEdge = x + borderInsets.left;
// int rightEdge = x + width - borderInsets.right;
// int topEdge = y + borderInsets.top;
// int bottomEdge = y + height - borderInsets.bottom;
Graphics2D g2 = (Graphics2D)graphics.create();
g2.setColor(lineColor);
//The location and size of the shadows depends on which shadows are being
//drawn. For instance, if the left & bottom shadows are being drawn, then
//the left shadow extends all the way down to the corner, a corner is drawn,
//and then the bottom shadow begins at the corner. If, however, only the
//bottom shadow is drawn, then the bottom-left corner is drawn to the
//right of the corner, and the bottom shadow is somewhat shorter than before.
Point topLeftShadowPoint = null;
if (showLeftShadow || showTopShadow) {
topLeftShadowPoint = new Point();
if (showLeftShadow && !showTopShadow) {
topLeftShadowPoint.setLocation(x, y + shadowSize);
} else if (showLeftShadow && showTopShadow) {
topLeftShadowPoint.setLocation(x, y);
} else if (!showLeftShadow && showTopShadow) {
topLeftShadowPoint.setLocation(x + shadowSize, y);
}
}
Point bottomLeftShadowPoint = null;
if (showLeftShadow || showBottomShadow) {
bottomLeftShadowPoint = new Point();
if (showLeftShadow && !showBottomShadow) {
bottomLeftShadowPoint.setLocation(x, y + height - shadowSize - shadowSize);
} else if (showLeftShadow && showBottomShadow) {
bottomLeftShadowPoint.setLocation(x, y + height - shadowSize);
} else if (!showLeftShadow && showBottomShadow) {
bottomLeftShadowPoint.setLocation(x + shadowSize, y + height - shadowSize);
}
}
Point bottomRightShadowPoint = null;
if (showRightShadow || showBottomShadow) {
bottomRightShadowPoint = new Point();
if (showRightShadow && !showBottomShadow) {
bottomRightShadowPoint.setLocation(x + width - shadowSize, y + height - shadowSize - shadowSize);
} else if (showRightShadow && showBottomShadow) {
bottomRightShadowPoint.setLocation(x + width - shadowSize, y + height - shadowSize);
} else if (!showRightShadow && showBottomShadow) {
bottomRightShadowPoint.setLocation(x + width - shadowSize - shadowSize, y + height - shadowSize);
}
}
Point topRightShadowPoint = null;
if (showRightShadow || showTopShadow) {
topRightShadowPoint = new Point();
if (showRightShadow && !showTopShadow) {
topRightShadowPoint.setLocation(x + width - shadowSize, y + shadowSize);
} else if (showRightShadow && showTopShadow) {
topRightShadowPoint.setLocation(x + width - shadowSize, y);
} else if (!showRightShadow && showTopShadow) {
topRightShadowPoint.setLocation(x + width - shadowSize - shadowSize, y);
}
}
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_SPEED);
if (showLeftShadow) {
Rectangle leftShadowRect =
new Rectangle(x,
topLeftShadowPoint.y + shadowSize,
shadowSize,
bottomLeftShadowPoint.y - topLeftShadowPoint.y - shadowSize);
g2.drawImage(images.get(Position.LEFT),
leftShadowRect.x, leftShadowRect.y,
leftShadowRect.width, leftShadowRect.height, null);
}
if (showBottomShadow) {
Rectangle bottomShadowRect =
new Rectangle(bottomLeftShadowPoint.x + shadowSize,
y + height - shadowSize,
bottomRightShadowPoint.x - bottomLeftShadowPoint.x - shadowSize,
shadowSize);
g2.drawImage(images.get(Position.BOTTOM),
bottomShadowRect.x, bottomShadowRect.y,
bottomShadowRect.width, bottomShadowRect.height, null);
}
if (showRightShadow) {
Rectangle rightShadowRect =
new Rectangle(x + width - shadowSize,
topRightShadowPoint.y + shadowSize,
shadowSize,
bottomRightShadowPoint.y - topRightShadowPoint.y - shadowSize);
g2.drawImage(images.get(Position.RIGHT),
rightShadowRect.x, rightShadowRect.y,
rightShadowRect.width, rightShadowRect.height, null);
}
if (showTopShadow) {
Rectangle topShadowRect =
new Rectangle(topLeftShadowPoint.x + shadowSize,
y,
topRightShadowPoint.x - topLeftShadowPoint.x - shadowSize,
shadowSize);
g2.drawImage(images.get(Position.TOP),
topShadowRect.x, topShadowRect.y,
topShadowRect.width, topShadowRect.height, null);
}
if (showLeftShadow || showTopShadow) {
g2.drawImage(images.get(Position.TOP_LEFT),
topLeftShadowPoint.x, topLeftShadowPoint.y, null);
}
if (showLeftShadow || showBottomShadow) {
g2.drawImage(images.get(Position.BOTTOM_LEFT),
bottomLeftShadowPoint.x, bottomLeftShadowPoint.y, null);
}
if (showRightShadow || showBottomShadow) {
g2.drawImage(images.get(Position.BOTTOM_RIGHT),
bottomRightShadowPoint.x, bottomRightShadowPoint.y, null);
}
if (showRightShadow || showTopShadow) {
g2.drawImage(images.get(Position.TOP_RIGHT),
topRightShadowPoint.x, topRightShadowPoint.y, null);
}
g2.dispose();
}
private Map<Position,BufferedImage> getImages(Graphics2D g2) {
//first, check to see if an image for this size has already been rendered
//if so, use the cache. Else, draw and save
Map<Position,BufferedImage> images = CACHE.get(shadowSize);
if (images == null) {
images = new HashMap<Position,BufferedImage>();
/*
* Do draw a drop shadow, I have to:
* 1) Create a rounded rectangle
* 2) Create a BufferedImage to draw the rounded rect in
* 3) Translate the graphics for the image, so that the rectangle
* is centered in the drawn space. The border around the rectangle
* needs to be shadowWidth wide, so that there is space for the
* shadow to be drawn.
* 4) Draw the rounded rect as black, with an opacity of 50%
* 5) Create the BLUR_KERNEL
* 6) Blur the image
* 7) copy off the corners, sides, etc into images to be used for
* drawing the Border
*/
int rectWidth = cornerSize + 1;
RoundRectangle2D rect = new RoundRectangle2D.Double(0, 0, rectWidth, rectWidth, cornerSize, cornerSize);
int imageWidth = rectWidth + shadowSize * 2;
BufferedImage image = GraphicsUtilities.createCompatibleTranslucentImage(imageWidth, imageWidth);
Graphics2D buffer = (Graphics2D)image.getGraphics();
buffer.setColor(new Color(0.0f, 0.0f, 0.0f, shadowOpacity));
buffer.translate(shadowSize, shadowSize);
buffer.fill(rect);
buffer.dispose();
float blurry = 1.0f / (float)(shadowSize * shadowSize);
float[] blurKernel = new float[shadowSize * shadowSize];
for (int i=0; i<blurKernel.length; i++) {
blurKernel[i] = blurry;
}
ConvolveOp blur = new ConvolveOp(new Kernel(shadowSize, shadowSize, blurKernel));
BufferedImage targetImage = GraphicsUtilities.createCompatibleTranslucentImage(imageWidth, imageWidth);
((Graphics2D)targetImage.getGraphics()).drawImage(image, blur, -(shadowSize/2), -(shadowSize/2));
int x = 1;
int y = 1;
int w = shadowSize;
int h = shadowSize;
images.put(Position.TOP_LEFT, getSubImage(targetImage, x, y, w, h));
x = 1;
y = h;
w = shadowSize;
h = 1;
images.put(Position.LEFT, getSubImage(targetImage, x, y, w, h));
x = 1;
y = rectWidth;
w = shadowSize;
h = shadowSize;
images.put(Position.BOTTOM_LEFT, getSubImage(targetImage, x, y, w, h));
x = cornerSize + 1;
y = rectWidth;
w = 1;
h = shadowSize;
images.put(Position.BOTTOM, getSubImage(targetImage, x, y, w, h));
x = rectWidth;
y = x;
w = shadowSize;
h = shadowSize;
images.put(Position.BOTTOM_RIGHT, getSubImage(targetImage, x, y, w, h));
x = rectWidth;
y = cornerSize + 1;
w = shadowSize;
h = 1;
images.put(Position.RIGHT, getSubImage(targetImage, x, y, w, h));
x = rectWidth;
y = 1;
w = shadowSize;
h = shadowSize;
images.put(Position.TOP_RIGHT, getSubImage(targetImage, x, y, w, h));
x = shadowSize;
y = 1;
w = 1;
h = shadowSize;
images.put(Position.TOP, getSubImage(targetImage, x, y, w, h));
image.flush();
CACHE.put(shadowSize, images);
}
return images;
}
/**
* Returns a new BufferedImage that represents a subregion of the given
* BufferedImage. (Note that this method does not use
* BufferedImage.getSubimage(), which will defeat image acceleration
* strategies on later JDKs.)
*/
private BufferedImage getSubImage(BufferedImage img,
int x, int y, int w, int h) {
BufferedImage ret = GraphicsUtilities.createCompatibleTranslucentImage(w, h);
Graphics2D g2 = ret.createGraphics();
g2.drawImage(img,
0, 0, w, h,
x, y, x+w, y+h,
null);
g2.dispose();
return ret;
}
/**
* @inheritDoc
*/
public Insets getBorderInsets(Component c) {
int top = showTopShadow ? lineWidth + shadowSize : lineWidth;
int left = showLeftShadow ? lineWidth + shadowSize : lineWidth;
int bottom = showBottomShadow ? lineWidth + shadowSize : lineWidth;
int right = showRightShadow ? lineWidth + shadowSize : lineWidth;
return new Insets(top, left, bottom, right);
}
/**
* @inheritDoc
*/
public boolean isBorderOpaque() {
return false;
}
public boolean isShowTopShadow() {
return showTopShadow;
}
public boolean isShowLeftShadow() {
return showLeftShadow;
}
public boolean isShowRightShadow() {
return showRightShadow;
}
public boolean isShowBottomShadow() {
return showBottomShadow;
}
public int getLineWidth() {
return lineWidth;
}
public Color getLineColor() {
return lineColor;
}
public int getShadowSize() {
return shadowSize;
}
public float getShadowOpacity() {
return shadowOpacity;
}
public int getCornerSize() {
return cornerSize;
}
}
|