Skip to content

Commit

Permalink
enable rotating images #232
Browse files Browse the repository at this point in the history
  • Loading branch information
mathisdt committed Jan 14, 2024
1 parent 6150d13 commit 371bdd9
Show file tree
Hide file tree
Showing 8 changed files with 236 additions and 156 deletions.
68 changes: 38 additions & 30 deletions src/main/java/org/zephyrsoft/sdb2/gui/MainWindow.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,28 +57,7 @@
import java.util.concurrent.ConcurrentMap;
import java.util.function.Consumer;

import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListSelectionModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JColorChooser;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JEditorPane;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
Expand Down Expand Up @@ -1497,11 +1476,8 @@ protected void handleSongPresent() {
* index, includes title as index 0 if the title is displayed
*/
protected void presentSong(Song song, SongPresentationPosition presentationPosition) {
Presentable presentable = song instanceof ImageSong imageSong
? new Presentable(null, imageSong.getFile().getAbsolutePath())
: new Presentable(song, null);
// not in a "contentChange" block because else the sections wouldn't be displayed:
boolean success = controller.present(presentable, presentationPosition);
boolean success = controller.present(new Presentable(song, null), presentationPosition);

controller.contentChange(() -> {
controller.stopSlideShow();
Expand Down Expand Up @@ -1765,8 +1741,8 @@ public void windowClosing(WindowEvent e) {
@Override
public void mouseClicked(MouseEvent e) {
try {
if (e.getClickCount() >= 2 && selectedSong != null) {
// double-clicked: put into present list
if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() >= 2 && selectedSong != null) {
// left double-clicked: put into present list
handleSongSelect();
}
} catch (Throwable ex) {
Expand Down Expand Up @@ -2157,9 +2133,41 @@ public void focusLost(FocusEvent e) {
@Override
public void mouseClicked(MouseEvent e) {
try {
if (e.getClickCount() >= 2 && presentListSelected != null) {
// double-clicked: present this song
if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() >= 2 && presentListSelected != null) {
// left double-clicked: present this song
handleSongPresent();
} else if (e.getButton() == MouseEvent.BUTTON3) {
// select item at mouse cursor position
int index = presentList.locationToIndex(e.getPoint());
if (presentModel.get(index) instanceof ImageSong imageSong) {
presentList.setSelectedIndex(index);
JPopupMenu rotateMenu = new JPopupMenu();
JMenuItem rotate90 = new JMenuItem("rotate right by 90°");
rotate90.addActionListener(ae -> {
imageSong.setRotateRight(90);
presentList.updateUI();
});
JMenuItem rotate270 = new JMenuItem("rotate left by 90°");
rotate270.addActionListener(ae -> {
imageSong.setRotateRight(270);
presentList.updateUI();
});
JMenuItem rotate180 = new JMenuItem("rotate by 180°");
rotate180.addActionListener(ae -> {
imageSong.setRotateRight(180);
presentList.updateUI();
});
JMenuItem rotate0 = new JMenuItem("reset rotation");
rotate0.addActionListener(ae -> {
imageSong.setRotateRight(0);
presentList.updateUI();
});
rotateMenu.add(rotate90);
rotateMenu.add(rotate270);
rotateMenu.add(rotate180);
rotateMenu.add(rotate0);
rotateMenu.show(presentList, e.getX(), e.getY());
}
}
} catch (Throwable ex) {
handleError(ex);
Expand Down
228 changes: 118 additions & 110 deletions src/main/java/org/zephyrsoft/sdb2/gui/SongCell.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,123 +15,131 @@
*/
package org.zephyrsoft.sdb2.gui;

import java.awt.*;

import javax.swing.*;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.Insets;

import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;

import org.zephyrsoft.sdb2.model.Song;
import org.zephyrsoft.sdb2.util.StringTools;
import org.zephyrsoft.sdb2.util.gui.ImageTools;

/**
* List entry for a {@link Song}.
*/
public class SongCell extends JPanel {

private static final long serialVersionUID = 6861947343987825552L;
public static final int TITLE_BOTTOM_SPACE = 5;
public static final int FIRSTLINE_BOTTOM_SPACE = 2;

private JLabel songTitle;
private JLabel firstLine;
private JLabel image;

/**
* Constructor.
*
* @param leftSpace space to insert left of the second line, in pixels
*/
public SongCell(Integer leftSpace) {
GridBagLayout gridBagLayout = new GridBagLayout();
gridBagLayout.columnWidths = new int[] { 0, 0, 0 };
gridBagLayout.rowHeights = new int[] { 0, 0, 0 };
gridBagLayout.columnWeights = new double[] { 0.0, 1.0, Double.MIN_VALUE };
gridBagLayout.rowWeights = new double[] { 0.0, 0.0, Double.MIN_VALUE };
setLayout(gridBagLayout);

image = new JLabel("<IMG>");
GridBagConstraints gbc_image = new GridBagConstraints();
gbc_image.gridheight = 2;
gbc_image.insets = new Insets(0, 0, 0, 10);
gbc_image.gridx = 0;
gbc_image.gridy = 0;
add(image, gbc_image);
// invisible when no image is explicitly set:
image.setVisible(false);

songTitle = new JLabel("<SONG TITLE>");
songTitle.setBorder(new EmptyBorder(2, 3, 0, 3));
GridBagConstraints gbcSongTitle = new GridBagConstraints();
gbcSongTitle.insets = new Insets(0, 0, TITLE_BOTTOM_SPACE, 0);
gbcSongTitle.fill = GridBagConstraints.HORIZONTAL;
gbcSongTitle.anchor = GridBagConstraints.NORTH;
gbcSongTitle.gridx = 1;
gbcSongTitle.gridy = 0;
add(songTitle, gbcSongTitle);

firstLine = new JLabel("<FIRST LINE>");
firstLine.setBorder(new EmptyBorder(0, 23, FIRSTLINE_BOTTOM_SPACE, 3));
if (leftSpace != null) {
firstLine.setBorder(new EmptyBorder(0, leftSpace + 3, FIRSTLINE_BOTTOM_SPACE, 3));
}
firstLine.setFont(new Font("SansSerif", Font.ITALIC, 10));
GridBagConstraints gbcFirstLine = new GridBagConstraints();
gbcFirstLine.anchor = GridBagConstraints.NORTH;
gbcFirstLine.fill = GridBagConstraints.HORIZONTAL;
gbcFirstLine.gridx = 1;
gbcFirstLine.gridy = 1;
add(firstLine, gbcFirstLine);
}

public String getSongTitle() {
return songTitle.getText();
}

public void setSongTitle(String text) {
if (StringTools.isEmpty(text)) {
// prevent a 0 pixel height:
songTitle.setText(" ");
} else {
songTitle.setText(text);
}
}

public String getFirstLine() {
return firstLine.getText();
}

public void setFirstLine(String text) {
if (StringTools.isEmpty(text)) {
// prevent a 0 pixel height:
firstLine.setText(" ");
} else {
firstLine.setText(text);
}
}

public void setImage(final String imageFile) {
if (imageFile == null) {
this.image.setVisible(false);
} else {
ImageIcon imageIcon = new ImageIcon(imageFile);
Image image = imageIcon.getImage();
int originalWidth = image.getWidth(null);
int originalHeight = image.getHeight(null);
double factor = (songTitle.getPreferredSize().getHeight() + firstLine.getPreferredSize().getHeight()
+ TITLE_BOTTOM_SPACE + FIRSTLINE_BOTTOM_SPACE) / (double) originalHeight;
image = image.getScaledInstance((int) (originalWidth * factor), (int) (originalHeight * factor), Image.SCALE_FAST);
this.image.setIcon(new ImageIcon(image));
this.image.setText("");
this.image.setVisible(true);
}
}

@Override
public void setForeground(Color color) {
if (songTitle != null && firstLine != null) {
songTitle.setForeground(color);
firstLine.setForeground(color);
}
}

private static final long serialVersionUID = 6861947343987825552L;
public static final int TITLE_BOTTOM_SPACE = 5;
public static final int FIRSTLINE_BOTTOM_SPACE = 2;
private JLabel songTitle;
private JLabel firstLine;
private JLabel image;
/**
* Constructor.
*
* @param leftSpace
* space to insert left of the second line, in pixels
*/
public SongCell(Integer leftSpace) {
GridBagLayout gridBagLayout = new GridBagLayout();
gridBagLayout.columnWidths = new int[] { 0, 0, 0 };
gridBagLayout.rowHeights = new int[] { 0, 0, 0 };
gridBagLayout.columnWeights = new double[] { 0.0, 1.0, Double.MIN_VALUE };
gridBagLayout.rowWeights = new double[] { 0.0, 0.0, Double.MIN_VALUE };
setLayout(gridBagLayout);
image = new JLabel("<IMG>");
GridBagConstraints gbc_image = new GridBagConstraints();
gbc_image.gridheight = 2;
gbc_image.insets = new Insets(0, 0, 0, 10);
gbc_image.gridx = 0;
gbc_image.gridy = 0;
add(image, gbc_image);
// invisible when no image is explicitly set:
image.setVisible(false);
songTitle = new JLabel("<SONG TITLE>");
songTitle.setBorder(new EmptyBorder(2, 3, 0, 3));
GridBagConstraints gbcSongTitle = new GridBagConstraints();
gbcSongTitle.insets = new Insets(0, 0, TITLE_BOTTOM_SPACE, 0);
gbcSongTitle.fill = GridBagConstraints.HORIZONTAL;
gbcSongTitle.anchor = GridBagConstraints.NORTH;
gbcSongTitle.gridx = 1;
gbcSongTitle.gridy = 0;
add(songTitle, gbcSongTitle);
firstLine = new JLabel("<FIRST LINE>");
firstLine.setBorder(new EmptyBorder(0, 23, FIRSTLINE_BOTTOM_SPACE, 3));
if (leftSpace != null) {
firstLine.setBorder(new EmptyBorder(0, leftSpace + 3, FIRSTLINE_BOTTOM_SPACE, 3));
}
firstLine.setFont(new Font("SansSerif", Font.ITALIC, 10));
GridBagConstraints gbcFirstLine = new GridBagConstraints();
gbcFirstLine.anchor = GridBagConstraints.NORTH;
gbcFirstLine.fill = GridBagConstraints.HORIZONTAL;
gbcFirstLine.gridx = 1;
gbcFirstLine.gridy = 1;
add(firstLine, gbcFirstLine);
}
public String getSongTitle() {
return songTitle.getText();
}
public void setSongTitle(String text) {
if (StringTools.isEmpty(text)) {
// prevent a 0 pixel height:
songTitle.setText(" ");
} else {
songTitle.setText(text);
}
}
public String getFirstLine() {
return firstLine.getText();
}
public void setFirstLine(String text) {
if (StringTools.isEmpty(text)) {
// prevent a 0 pixel height:
firstLine.setText(" ");
} else {
firstLine.setText(text);
}
}
public void setImage(final String imageFile, int degreesToRotateRight) {
if (imageFile == null) {
this.image.setVisible(false);
} else {
ImageIcon imageIcon = new ImageIcon(imageFile);
Image image = imageIcon.getImage();
image = ImageTools.rotate(image, degreesToRotateRight);
double factor = (songTitle.getPreferredSize().getHeight() + firstLine.getPreferredSize().getHeight()
+ TITLE_BOTTOM_SPACE + FIRSTLINE_BOTTOM_SPACE) * 2 / image.getHeight(null);
image = ImageTools.scale(image, factor);
this.image.setIcon(new ImageIcon(image));
this.image.setText("");
this.image.setVisible(true);
}
}
@Override
public void setForeground(Color color) {
if (songTitle != null && firstLine != null) {
songTitle.setForeground(color);
firstLine.setForeground(color);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ public Component getListCellRendererComponent(JList<? extends Song> list, Song v
ret.setSongTitle(value.getTitle() != null ? value.getTitle() : "");
ret.setFirstLine(SongParser.getFirstLyricsLine(value));
if (value instanceof ImageSong imageSong) {
ret.setImage(imageSong.getFile().getAbsolutePath());
ret.setImage(imageSong.getFile().getAbsolutePath(), imageSong.getRotateRight());
}
}

Expand Down
8 changes: 8 additions & 0 deletions src/main/java/org/zephyrsoft/sdb2/model/ImageSong.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

public class ImageSong extends Song {
private final File file;
private int rotateRight = 0;

public ImageSong(final File file) {
super(UUID.randomUUID().toString());
Expand All @@ -15,6 +16,13 @@ public File getFile() {
return file;
}

public int getRotateRight() {
return rotateRight;
}

public void setRotateRight(final int rotateRight) {
this.rotateRight = rotateRight;
}
@Override
public String getTitle() {
return file != null ? file.getName() : "empty";
Expand Down
4 changes: 3 additions & 1 deletion src/main/java/org/zephyrsoft/sdb2/model/SongsModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,9 @@ public TransparentFilterableListModel<Song> getFilterableListModel() {
createdListModels.add(createdListModel);
return createdListModel;
}

public Song get(final int index) {
return songs.get(index);
}
public int getSize() {
return songs.size();
}
Expand Down
Loading

0 comments on commit 371bdd9

Please sign in to comment.