mirror of
https://gitlab.com/biskuteri-cafe/JKomasto2.git
synced 2024-11-20 05:04:51 +01:00
e6fea4c061
(Before this, JKomasto and sometimes the Mastodon web client would get '411 Record Not Found' when submitting the same text after deleting and redrafting. Presumably the Mastodon server caches both whether an idempotency key was fulfilled and which post it leads to, and for some reason it looks up the second and fails.)
325 lines
6.0 KiB
Java
325 lines
6.0 KiB
Java
|
|
import javax.swing.JFrame;
|
|
import javax.swing.JPanel;
|
|
import javax.swing.JButton;
|
|
import javax.swing.ImageIcon;
|
|
import java.awt.Graphics;
|
|
import java.awt.Image;
|
|
import java.awt.Dimension;
|
|
import java.awt.FontMetrics;
|
|
import java.awt.BorderLayout;
|
|
import java.awt.event.ActionListener;
|
|
import java.awt.event.ActionEvent;
|
|
import java.awt.event.MouseListener;
|
|
import java.awt.event.MouseMotionListener;
|
|
import java.awt.event.MouseEvent;
|
|
import java.awt.event.MouseWheelListener;
|
|
import java.awt.event.MouseWheelEvent;
|
|
import java.awt.Image;
|
|
import java.net.URL;
|
|
import java.net.MalformedURLException;
|
|
|
|
class
|
|
ImageWindow extends JFrame {
|
|
|
|
private Attachment[]
|
|
attachments;
|
|
|
|
private int
|
|
offset;
|
|
|
|
// - -%- -
|
|
|
|
private ImageComponent
|
|
display;
|
|
|
|
// ---%-@-%---
|
|
|
|
public synchronized void
|
|
showAttachments(Attachment[] attachments)
|
|
{
|
|
this.attachments = attachments;
|
|
|
|
if (attachments.length == 0) {
|
|
display.setImage(null);
|
|
display.setNext(null);
|
|
display.setPrev(null);
|
|
display.repaint();
|
|
return;
|
|
}
|
|
|
|
toImage(offset = 0);
|
|
}
|
|
|
|
public void
|
|
toNextImage()
|
|
{
|
|
if (attachments.length == 0) return;
|
|
assert offset < attachments.length - 1;
|
|
toImage(++offset);
|
|
}
|
|
|
|
public void
|
|
toPrevImage()
|
|
{
|
|
if (attachments.length == 0) return;
|
|
assert offset > 0;
|
|
toImage(--offset);
|
|
}
|
|
|
|
// - -%- -
|
|
|
|
private synchronized void
|
|
toImage(int offset)
|
|
{
|
|
int last = attachments.length - 1;
|
|
assert offset >= 0;
|
|
assert offset < attachments.length;
|
|
|
|
Attachment prev, curr, next;
|
|
curr = attachments[offset];
|
|
next = offset < last ? attachments[offset + 1] : null;
|
|
prev = offset > 0 ? attachments[offset - 1] : null;
|
|
|
|
display.setImage(curr.image);
|
|
display.setNext(next != null ? next.image : null);
|
|
display.setPrev(prev != null ? prev.image : null);
|
|
|
|
if (!curr.type.equals("image"))
|
|
display.setToolTipText(
|
|
display.getToolTipText()
|
|
+ "\n(Media is of type '" + curr.type + "')"
|
|
);
|
|
|
|
repaint();
|
|
}
|
|
|
|
// ---%-@-%---
|
|
|
|
ImageWindow()
|
|
{
|
|
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
|
|
setSize(600, 600);
|
|
|
|
display = new ImageComponent(this);
|
|
showAttachments(new Attachment[0]);
|
|
setContentPane(display);
|
|
}
|
|
|
|
}
|
|
|
|
class
|
|
ImageComponent extends JPanel
|
|
implements
|
|
ActionListener,
|
|
MouseListener, MouseMotionListener, MouseWheelListener {
|
|
|
|
private ImageWindow
|
|
primaire;
|
|
|
|
// - -%- -
|
|
|
|
private Image
|
|
image, prevImage, nextImage;
|
|
|
|
private JPanel
|
|
buttonArea;
|
|
|
|
private JButton
|
|
prev, next, toggle;
|
|
|
|
private boolean
|
|
scaleImage;
|
|
|
|
private int
|
|
xOffset, yOffset, zoomLevel;
|
|
|
|
private int
|
|
dragX, dragY, xPOffset, yPOffset;
|
|
|
|
// ---%-@-%---
|
|
|
|
public void
|
|
setImage(Image image)
|
|
{
|
|
this.image = image;
|
|
if (image != null) {
|
|
Object p = image.getProperty("comment", this);
|
|
String desc = p instanceof String ? (String)p : null;
|
|
setToolTipText(desc);
|
|
}
|
|
xOffset = yOffset = xPOffset = yPOffset = 0;
|
|
zoomLevel = 100;
|
|
}
|
|
|
|
public void
|
|
setPrev(Image image)
|
|
{
|
|
prev.setEnabled(image != null);
|
|
prev.setText(image == null ? "<" : "");
|
|
prev.setIcon(toIcon(image));
|
|
}
|
|
|
|
public void
|
|
setNext(Image image)
|
|
{
|
|
next.setEnabled(image != null);
|
|
next.setText(image == null ? ">" : "");
|
|
next.setIcon(toIcon(image));
|
|
}
|
|
|
|
// - -%- -
|
|
|
|
public void
|
|
actionPerformed(ActionEvent eA)
|
|
{
|
|
if (eA.getSource() == prev) primaire.toPrevImage();
|
|
if (eA.getSource() == next) primaire.toNextImage();
|
|
if (eA.getSource() == toggle) {
|
|
scaleImage = !scaleImage;
|
|
if (scaleImage) toggle.setText("Show unscaled");
|
|
else toggle.setText("Show scaled to window");
|
|
setImage(this.image);
|
|
repaint();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public void
|
|
mousePressed(MouseEvent eM)
|
|
{
|
|
dragX = eM.getX();
|
|
dragY = eM.getY();
|
|
}
|
|
|
|
public void
|
|
mouseDragged(MouseEvent eM)
|
|
{
|
|
int dx = eM.getX() - dragX;
|
|
int dy = eM.getY() - dragY;
|
|
xPOffset = dx;
|
|
yPOffset = dy;
|
|
repaint();
|
|
}
|
|
|
|
public void
|
|
mouseReleased(MouseEvent eM)
|
|
{
|
|
xOffset += xPOffset;
|
|
yOffset += yPOffset;
|
|
xPOffset = yPOffset = 0;
|
|
}
|
|
|
|
public void
|
|
mouseWheelMoved(MouseWheelEvent eMw)
|
|
{
|
|
zoomLevel += 10 * -eMw.getUnitsToScroll();
|
|
if (zoomLevel < 50) zoomLevel = 50;
|
|
if (zoomLevel > 400) zoomLevel = 400;
|
|
repaint();
|
|
}
|
|
|
|
|
|
public void
|
|
mouseEntered(MouseEvent eM) { }
|
|
|
|
public void
|
|
mouseExited(MouseEvent eM) { }
|
|
|
|
public void
|
|
mouseClicked(MouseEvent eM) { }
|
|
|
|
public void
|
|
mouseMoved(MouseEvent eM) { }
|
|
|
|
// - -%- -
|
|
|
|
private static ImageIcon
|
|
toIcon(Image image)
|
|
{
|
|
if (image == null) return null;
|
|
return new ImageIcon(image);
|
|
}
|
|
|
|
// ---%-@-%---
|
|
|
|
private class
|
|
Painter extends JPanel {
|
|
|
|
protected void
|
|
paintComponent(Graphics g)
|
|
{
|
|
if (image == null)
|
|
{
|
|
String str =
|
|
"(There are no images being displayed.)";
|
|
FontMetrics fm = g.getFontMetrics();
|
|
int x = (getWidth() - fm.stringWidth(str)) / 2;
|
|
int y = (getHeight() + fm.getHeight()) / 2;
|
|
g.drawString(str, x, y);
|
|
return;
|
|
}
|
|
int wo = image.getWidth(this);
|
|
int ho = image.getHeight(this);
|
|
int wn, hn;
|
|
if (wo > ho) {
|
|
wn = scaleImage ? getWidth() : wo;
|
|
hn = ho * wn / wo;
|
|
}
|
|
else {
|
|
hn = scaleImage ? getHeight() : ho;
|
|
wn = wo * hn / ho;
|
|
}
|
|
wn = wn * zoomLevel / 100;
|
|
hn = hn * zoomLevel / 100;
|
|
int x = (getWidth() - wn) / 2;
|
|
int y = (getHeight() - hn) / 2;
|
|
x += xOffset + xPOffset;
|
|
y += yOffset + yPOffset;
|
|
g.drawImage(image, x, y, wn, hn, this);
|
|
}
|
|
|
|
}
|
|
|
|
// ---%-@-%---
|
|
|
|
ImageComponent(ImageWindow primaire)
|
|
{
|
|
this.primaire = primaire;
|
|
|
|
Dimension BUTTON_SIZE = new Dimension(48, 48);
|
|
|
|
setOpaque(false);
|
|
scaleImage = true;
|
|
zoomLevel = 100;
|
|
|
|
prev = new JButton();
|
|
toggle = new JButton("Show unscaled");
|
|
next = new JButton();
|
|
prev.setPreferredSize(BUTTON_SIZE);
|
|
next.setPreferredSize(BUTTON_SIZE);
|
|
prev.addActionListener(this);
|
|
toggle.addActionListener(this);
|
|
next.addActionListener(this);
|
|
|
|
buttonArea = new JPanel();
|
|
buttonArea.setOpaque(false);
|
|
buttonArea.add(prev);
|
|
buttonArea.add(toggle);
|
|
buttonArea.add(next);
|
|
|
|
setPrev(null);
|
|
setNext(null);
|
|
|
|
setLayout(new BorderLayout());
|
|
add(buttonArea, BorderLayout.SOUTH);
|
|
add(new Painter(), BorderLayout.CENTER);
|
|
|
|
addMouseListener(this);
|
|
addMouseMotionListener(this);
|
|
addMouseWheelListener(this);
|
|
}
|
|
|
|
}
|