package com.ts3client.ui; import javax.swing.JComponent; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.RenderingHints; import java.awt.Toolkit; /** * Paints an avatar scaled to fit, keeping its aspect ratio. The image is a Toolkit * image drawn with this component as its observer, so an animated GIF keeps playing: * each decoded frame triggers a repaint. */ final class AvatarView extends JComponent { private final int boxSize; private Image image; private int imageWidth = -1; private int imageHeight = -1; AvatarView(int boxSize) { this.boxSize = boxSize; setPreferredSize(new Dimension(boxSize, boxSize)); setMinimumSize(getPreferredSize()); } /** @param data the encoded image, or {@code null} to show nothing */ void setImage(byte[] data) { if (image != null) image.flush(); image = data == null ? null : Toolkit.getDefaultToolkit().createImage(data); imageWidth = imageHeight = -1; repaint(); } boolean hasImage() { return image != null; } @Override protected void paintComponent(Graphics g) { if (image == null) return; if (imageWidth < 0 || imageHeight < 0) { // Unknown until the header is decoded; the observer repaints once it is. imageWidth = image.getWidth(this); imageHeight = image.getHeight(this); if (imageWidth < 0 || imageHeight < 0) return; } double scale = Math.min(1.0, Math.min((double) getWidth() / imageWidth, (double) getHeight() / imageHeight)); int w = Math.max(1, (int) Math.round(imageWidth * scale)); int h = Math.max(1, (int) Math.round(imageHeight * scale)); Graphics2D g2 = (Graphics2D) g.create(); try { g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); g2.drawImage(image, (getWidth() - w) / 2, (getHeight() - h) / 2, w, h, this); } finally { g2.dispose(); } } int boxSize() { return boxSize; } }