Show client avatars and let the user set their own
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>
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user