package net.homelinux.nikiroo.utils.gui; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Insets; import java.awt.LayoutManager; import java.awt.Paint; import java.awt.Rectangle; import javax.swing.ImageIcon; import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JViewport; /** * Support custom painting on a panel in the form of
  • images - that can be * scaled, tiled or painted at original size
  • non solid painting - that * can be done by using a Paint object
  • Also, any component added directly * to this panel will be made non-opaque so that the custom painting can show * through. */ public class JBackgroundPanel extends JPanel { private static final long serialVersionUID = 1L; public static final int SCALED = 0; public static final int TILED = 1; public static final int ACTUAL = 2; public static final int RATIO = 3; private Paint painter; private Image image; private int style = SCALED; private float alignmentX = 0.5f; private float alignmentY = 0.5f; private boolean isTransparentAdd = true; /** * Empty {@link JBackgroundPanel}. */ public JBackgroundPanel() { } /** * Empty {@link JBackgroundPanel} with the given {@link LayoutManager}. */ public JBackgroundPanel(LayoutManager layout) { super(layout); } /* * Set image as the background with the SCALED style */ public JBackgroundPanel(ImageIcon image) { this(image.getImage()); } /* * Set image as the background with the SCALED style */ public JBackgroundPanel(ImageIcon image, int style) { this(image.getImage(), style); } /* * Set image as the backround with the specified style and alignment */ public JBackgroundPanel(ImageIcon image, int style, float alignmentX, float alignmentY) { this(image.getImage(), style, alignmentX, alignmentY); } /* * Set image as the background with the SCALED style */ public JBackgroundPanel(Image image) { this(image, SCALED); } /* * Set image as the background with the specified style */ public JBackgroundPanel(Image image, int style) { setImage(image); setStyle(style); setLayout(new BorderLayout()); } /* * Set image as the backround with the specified style and alignment */ public JBackgroundPanel(Image image, int style, float alignmentX, float alignmentY) { setImage(image); setStyle(style); setImageAlignmentX(alignmentX); setImageAlignmentY(alignmentY); setLayout(new BorderLayout()); } /* * Use the Paint interface to paint a background */ public JBackgroundPanel(Paint painter) { setPaint(painter); setLayout(new BorderLayout()); } /* * Set the image used as the background */ public void setImage(Image image) { this.image = image; repaint(); } /* * Set the style used to paint the background image */ public void setStyle(int style) { this.style = style; repaint(); } /* * Set the Paint object used to paint the background */ public void setPaint(Paint painter) { this.painter = painter; repaint(); } /* * Specify the horizontal alignment of the image when using ACTUAL style */ public void setImageAlignmentX(float alignmentX) { this.alignmentX = alignmentX > 1.0f ? 1.0f : alignmentX < 0.0f ? 0.0f : alignmentX; repaint(); } /* * Specify the horizontal alignment of the image when using ACTUAL style */ public void setImageAlignmentY(float alignmentY) { this.alignmentY = alignmentY > 1.0f ? 1.0f : alignmentY < 0.0f ? 0.0f : alignmentY; repaint(); } /* * Override method so we can make the component transparent */ public void add(JComponent component) { add(component, null); } /* * Override to provide a preferred size equal to the image size */ @Override public Dimension getPreferredSize() { if (image == null) return super.getPreferredSize(); else return new Dimension(image.getWidth(null), image.getHeight(null)); } /* * Override method so we can make the component transparent */ public void add(JComponent component, Object constraints) { if (isTransparentAdd) { makeComponentTransparent(component); } super.add(component, constraints); } /* * Controls whether components added to this panel should automatically be * made transparent. That is, setOpaque(false) will be invoked. The default * is set to true. */ public void setTransparentAdd(boolean isTransparentAdd) { this.isTransparentAdd = isTransparentAdd; } /* * Try to make the component transparent. For components that use renderers, * like JTable, you will also need to change the renderer to be transparent. * An easy way to do this it to set the background of the table to a Color * using an alpha value of 0. */ private void makeComponentTransparent(JComponent component) { component.setOpaque(false); if (component instanceof JScrollPane) { JScrollPane scrollPane = (JScrollPane) component; JViewport viewport = scrollPane.getViewport(); viewport.setOpaque(false); Component c = viewport.getView(); if (c instanceof JComponent) { ((JComponent) c).setOpaque(false); } } } /* * Add custom painting */ @Override protected void paintComponent(Graphics g) { super.paintComponent(g); // Invoke the painter for the background if (painter != null) { Dimension d = getSize(); Graphics2D g2 = (Graphics2D) g; g2.setPaint(painter); g2.fill(new Rectangle(0, 0, d.width, d.height)); } // Draw the image if (image == null) return; switch (style) { case RATIO: drawRatio(g); break; case SCALED: drawScaled(g); break; case TILED: drawTiled(g); break; case ACTUAL: drawActual(g); break; default: drawScaled(g); } } /* * Custom painting code for drawing a SCALED image as the background */ private void drawScaled(Graphics g) { Dimension d = getSize(); g.drawImage(image, 0, 0, d.width, d.height, null); } /* * Custom painting code for drawing TILED images as the background */ private void drawTiled(Graphics g) { Dimension d = getSize(); int width = image.getWidth(null); int height = image.getHeight(null); for (int x = 0; x < d.width; x += width) { for (int y = 0; y < d.height; y += height) { g.drawImage(image, x, y, null, null); } } } /* * Custom painting code for drawing the ACTUAL image as the background. The * image is positioned in the panel based on the horizontal and vertical * alignments specified. */ private void drawActual(Graphics g) { Dimension d = getSize(); Insets insets = getInsets(); int width = d.width - insets.left - insets.right; int height = d.height - insets.top - insets.left; float x = (width - image.getWidth(null)) * alignmentX; float y = (height - image.getHeight(null)) * alignmentY; g.drawImage(image, (int) x + insets.left, (int) y + insets.top, this); } private void drawRatio(Graphics g) { if (image != null && g != null) { // si la dimension actuelle est > � la preferedSize (qui est // elle-meme a la taille de l'avatar) int h = (this.getHeight() - image.getHeight(null)) / 2; int w = (this.getWidth() - image.getWidth(null)) / 2; if (h < 0) { h = 0; } if (w < 0) { w = 0; } // TODO: alignment, solid paint g.drawImage(image, w, h, null, null); } } }