adds edit option for screenshots

This commit is contained in:
mikael.lantz 2021-01-08 16:42:55 +01:00
parent eec978a707
commit 8c633b521c
10 changed files with 505 additions and 10 deletions

View File

@ -28,7 +28,9 @@ import javax.swing.filechooser.FileNameExtensionFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import se.lantz.gui.screenshot.EditScreenshotDialog;
import se.lantz.model.InfoModel;
import se.lantz.model.data.GameView;
import se.lantz.util.FileDrop;
import se.lantz.util.FileManager;
@ -66,7 +68,7 @@ public class ScreenshotsPanel extends JPanel
private ImageIcon warningIcon = new ImageIcon(getClass().getResource("/se/lantz/warning-icon.png"));
private String editTooltip =
"<html>Optimal resolution for the carousel is 320x200.<br>Press to crop the image to this size (the border will be removed).<br>It will be resized when saving but it might make it blurry.</html>";
"<html>Optimal resolution for the carousel is 320x200.<br>Press to edit the image.<br>It will be resized when the game is saved but it might make it blurry.</html>";
private boolean gamesFileUpdated = false;
FileNameExtensionFilter imagefilter =
@ -107,7 +109,7 @@ public class ScreenshotsPanel extends JPanel
model.addPropertyChangeListener((e) -> modelChanged());
}
}
public void resetWhenSaved()
{
currentCoverFile = "";
@ -596,10 +598,31 @@ public class ScreenshotsPanel extends JPanel
{
public void actionPerformed(ActionEvent arg0)
{
BufferedImage croppedImage = FileManager.cropImageTo320x200(currentScreen1Image);
getScreen1ImageLabel().setIcon(new ImageIcon(croppedImage));
model.setScreen1Image(croppedImage);
edit1Button.setVisible(false);
JPopupMenu menu = new JPopupMenu();
JMenuItem autoEditItem = new JMenuItem("Crop automatically to 320x200");
autoEditItem.addActionListener(e -> {
BufferedImage croppedImage = FileManager.cropImageTo320x200(currentScreen1Image);
getScreen1ImageLabel().setIcon(new ImageIcon(croppedImage));
model.setScreen1Image(croppedImage);
edit1Button.setVisible(false);
});
menu.add(autoEditItem);
JMenuItem manEditItem = new JMenuItem("Crop manually...");
manEditItem.addActionListener(e -> {
EditScreenshotDialog dialog = new EditScreenshotDialog(currentScreen1Image);
dialog.pack();
dialog.setLocationRelativeTo(MainWindow.getInstance());
if (dialog.showDialog())
{
BufferedImage croppedImage = dialog.getEditedImage();
getScreen1ImageLabel().setIcon(new ImageIcon(croppedImage));
model.setScreen1Image(croppedImage);
edit1Button.setVisible(false);
}
});
menu.add(manEditItem);
menu.show(edit1Button, 15, 15);
}
});
edit1Button.setMargin(new Insets(1, 3, 1, 3));
@ -618,10 +641,31 @@ public class ScreenshotsPanel extends JPanel
{
public void actionPerformed(ActionEvent arg0)
{
BufferedImage croppedImage = FileManager.cropImageTo320x200(currentScreen2Image);
getScreen2ImageLabel().setIcon(new ImageIcon(croppedImage));
model.setScreen2Image(croppedImage);
edit2Button.setVisible(false);
JPopupMenu menu = new JPopupMenu();
JMenuItem autoEditItem = new JMenuItem("Crop automatically to 320x200");
autoEditItem.addActionListener(e -> {
BufferedImage croppedImage = FileManager.cropImageTo320x200(currentScreen2Image);
getScreen2ImageLabel().setIcon(new ImageIcon(croppedImage));
model.setScreen2Image(croppedImage);
edit2Button.setVisible(false);
});
menu.add(autoEditItem);
JMenuItem manEditItem = new JMenuItem("Crop manually...");
manEditItem.addActionListener(e -> {
EditScreenshotDialog dialog = new EditScreenshotDialog(currentScreen2Image);
dialog.pack();
dialog.setLocationRelativeTo(MainWindow.getInstance());
if (dialog.showDialog())
{
BufferedImage croppedImage = dialog.getEditedImage();
getScreen2ImageLabel().setIcon(new ImageIcon(croppedImage));
model.setScreen2Image(croppedImage);
edit2Button.setVisible(false);
}
});
menu.add(manEditItem);
menu.show(edit2Button, 15, 15);
}
});
edit2Button.setMargin(new Insets(1, 3, 1, 3));

View File

@ -0,0 +1,51 @@
package se.lantz.gui.screenshot;
import java.awt.BorderLayout;
import java.awt.Frame;
import java.awt.image.BufferedImage;
import javax.swing.JPanel;
import se.lantz.gui.BaseDialog;
import se.lantz.gui.MainWindow;
import se.lantz.manager.ScraperManager;
import se.lantz.model.data.ScraperFields;
public class EditScreenshotDialog extends BaseDialog
{
private EditScreenshotPanel editScreenPanel;
private BufferedImage originalScreen;
public EditScreenshotDialog(BufferedImage originalScreen)
{
super(MainWindow.getInstance());
setTitle("Edit screenshot");
this.originalScreen = originalScreen;
JPanel content = new JPanel();
content.setLayout(new BorderLayout());
content.add(getEditScreenshotPanel(), BorderLayout.CENTER);
addContent(content);
getEditScreenshotPanel().setImage(originalScreen);
this.setResizable(false);
}
private EditScreenshotPanel getEditScreenshotPanel()
{
if (editScreenPanel == null)
{
editScreenPanel = new EditScreenshotPanel();
}
return editScreenPanel;
}
@Override
public boolean showDialog()
{
return super.showDialog();
}
public BufferedImage getEditedImage()
{
return getEditScreenshotPanel().getCroppedImage();
}
}

View File

@ -0,0 +1,295 @@
package se.lantz.gui.screenshot;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import javax.swing.AbstractAction;
import javax.swing.ImageIcon;
import javax.swing.InputMap;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.JCheckBox;
public class EditScreenshotPanel extends JPanel
{
private JLabel imageLabel;
private JPanel buttonPanel;
private TypomaticButton leftButton;
private TypomaticButton righButton;
private BufferedImage image;
private int x = 0;
private int y = 0;
private int width = 320;
private int height = 200;
private TypomaticButton upButton;
private TypomaticButton downButton;
private JLabel infoLabel;
private JCheckBox largeSizeCheckBox;
public EditScreenshotPanel()
{
GridBagLayout gridBagLayout = new GridBagLayout();
setLayout(gridBagLayout);
GridBagConstraints gbc_infoLabel = new GridBagConstraints();
gbc_infoLabel.insets = new Insets(10, 5, 5, 0);
gbc_infoLabel.gridx = 0;
gbc_infoLabel.gridy = 0;
add(getInfoLabel(), gbc_infoLabel);
GridBagConstraints gbc_imageLabel = new GridBagConstraints();
gbc_imageLabel.fill = GridBagConstraints.BOTH;
gbc_imageLabel.weighty = 1.0;
gbc_imageLabel.insets = new Insets(10, 10, 10, 10);
gbc_imageLabel.weightx = 1.0;
gbc_imageLabel.gridx = 0;
gbc_imageLabel.gridy = 1;
add(getImageLabel(), gbc_imageLabel);
GridBagConstraints gbc_largeSizeCheckBox = new GridBagConstraints();
gbc_largeSizeCheckBox.insets = new Insets(0, 0, 5, 0);
gbc_largeSizeCheckBox.gridx = 0;
gbc_largeSizeCheckBox.gridy = 2;
add(getLargeSizeCheckBox(), gbc_largeSizeCheckBox);
GridBagConstraints gbc_buttonPanel = new GridBagConstraints();
gbc_buttonPanel.anchor = GridBagConstraints.NORTH;
gbc_buttonPanel.gridx = 0;
gbc_buttonPanel.gridy = 3;
add(getButtonPanel(), gbc_buttonPanel);
InputMap inputMap = this.getInputMap(WHEN_IN_FOCUSED_WINDOW);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "left");
getActionMap().put("left", new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
performLeftAction();
}
});
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "right");
getActionMap().put("right", new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
performRightAction();
}
});
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "up");
getActionMap().put("up", new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
performUpAction();
}
});
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), "down");
getActionMap().put("down", new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
performDownAction();
}
});
}
private void performLeftAction()
{
if (x > 0)
{
x = x - 1;
updateLabelIcon();
}
}
private void performRightAction()
{
if (x < (image.getWidth() - width - 1))
{
x = x + 1;
updateLabelIcon();
}
}
private void performUpAction()
{
if (y > 0)
{
y = y - 1;
updateLabelIcon();
}
}
private void performDownAction()
{
if (y < (image.getHeight() - height - 1))
{
y = y + 1;
updateLabelIcon();
}
}
private JLabel getImageLabel()
{
if (imageLabel == null)
{
imageLabel = new JLabel("");
}
return imageLabel;
}
private JPanel getButtonPanel()
{
if (buttonPanel == null)
{
buttonPanel = new JPanel();
buttonPanel.add(getLeftButton());
buttonPanel.add(getRighButton());
buttonPanel.add(getUpButton());
buttonPanel.add(getDownButton());
}
return buttonPanel;
}
private TypomaticButton getLeftButton()
{
if (leftButton == null)
{
leftButton = new TypomaticButton("");
leftButton.setIcon(new ImageIcon(this.getClass().getResource("/se/lantz/arrow-plain-left.png")));
leftButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent arg0)
{
performLeftAction();
}
});
}
return leftButton;
}
private TypomaticButton getRighButton()
{
if (righButton == null)
{
righButton = new TypomaticButton("");
righButton.setIcon(new ImageIcon(this.getClass().getResource("/se/lantz/arrow-plain-right.png")));
righButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent arg0)
{
performRightAction();
}
});
}
return righButton;
}
public void setImage(BufferedImage image)
{
this.image = image;
getLargeSizeCheckBox().setVisible(image.getWidth() > 447 && image.getHeight() > 279);
x = (image.getWidth() - width) / 2;
y = ((image.getHeight() - height) / 2) - 1;
updateLabelIcon();
}
private void updateLabelIcon()
{
BufferedImage copyOfImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics g = copyOfImage.createGraphics();
g.drawImage(image, 0, 0, null);
g.setColor(Color.red);
g.drawRect(x, y, width, height);
getImageLabel().setIcon(new ImageIcon(copyOfImage));
}
public BufferedImage getImage()
{
return this.image;
}
private TypomaticButton getUpButton()
{
if (upButton == null)
{
upButton = new TypomaticButton("");
upButton.setIcon(new ImageIcon(this.getClass().getResource("/se/lantz/arrow-plain-up.png")));
upButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
performUpAction();
}
});
}
return upButton;
}
private TypomaticButton getDownButton()
{
if (downButton == null)
{
downButton = new TypomaticButton("");
downButton.setIcon(new ImageIcon(this.getClass().getResource("/se/lantz/arrow-plain-down.png")));
downButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
performDownAction();
}
});
}
return downButton;
}
public BufferedImage getCroppedImage()
{
BufferedImage newImage = image
.getSubimage(x, y, width, height);
BufferedImage copyOfImage =
new BufferedImage(newImage.getWidth(), newImage.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics g = copyOfImage.createGraphics();
g.drawImage(newImage, 0, 0, null);
return newImage;
}
private JLabel getInfoLabel() {
if (infoLabel == null) {
infoLabel = new JLabel("Move the rectangle to decide where to crop the image");
}
return infoLabel;
}
private JCheckBox getLargeSizeCheckBox() {
if (largeSizeCheckBox == null) {
largeSizeCheckBox = new JCheckBox("Crop to 448x280 (image will be resized)");
largeSizeCheckBox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (largeSizeCheckBox.isSelected())
{
width = 448;
height = 280;
}
else
{
width = 320;
height = 200;
}
x = (image.getWidth() - width) / 2;
y = ((image.getHeight() - height) / 2) - 1;
updateLabelIcon();
}
});
}
return largeSizeCheckBox;
}
}

View File

@ -0,0 +1,105 @@
package se.lantz.gui.screenshot;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.SwingUtilities;
public class TypomaticButton extends JButton implements MouseListener
{
private final int SPEED = 25;
private final int WAIT = 150;
private boolean autotype = false;
private static Thread theThread = null;
private String myName = "unknown";
private int speed = SPEED, wait = WAIT, decrement = (wait - speed) / 10;
TypomaticButton(Action action)
{
super(action);
myName = action.getValue(Action.NAME).toString();
addMouseListener(this);
}
TypomaticButton(String text)
{
super(text);
setBorder(BorderFactory.createEmptyBorder(6, 6, 6, 6));
myName = text;
addMouseListener(this);
}
@Override
public void mouseClicked(MouseEvent arg0)
{
}
@Override
public void mouseEntered(MouseEvent arg0)
{
}
@Override
public void mouseExited(MouseEvent arg0)
{
}
@Override
public void mousePressed(MouseEvent arg0)
{
autotype = true;
theThread = new Thread(new Runnable()
{ // do it on a new thread so we don't block the UI thread
@Override
public void run()
{
for (int i = 10000; i > 0 && autotype; i--)
{ // don't go on for ever
try
{
Thread.sleep(wait); // wait awhile
}
catch (InterruptedException e)
{
break;
}
if (wait != speed)
{
wait = wait - decrement; // gradually accelerate to top speed
if (wait < speed)
wait = speed;
}
SwingUtilities.invokeLater(new Runnable()
{ // run this bit on the UI thread
public void run()
{
if (!autotype) // it may have been stopped meanwhile
return;
ActionListener[] als = getActionListeners();
for (ActionListener al : als)
{ // distribute to all listeners
ActionEvent aevent = new ActionEvent(getClass(), 0, myName);
al.actionPerformed(aevent);
}
}
});
}
autotype = false;
}
});
theThread.start();
}
@Override
public void mouseReleased(MouseEvent arg0)
{
autotype = false;
wait = WAIT;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 445 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 332 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 334 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 328 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 313 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 455 B