Avatars are fetched from the server's file repository as /avatar_<id>, verified against client_flag_avatar and cached on disk; animated GIFs play in the info panel. Self > Set avatar... uploads or removes our own picture within the server's size limit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
66 lines
2.1 KiB
Java
66 lines
2.1 KiB
Java
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;
|
|
}
|
|
}
|