/* You may freely copy, distribute, modify and use this class as long as the original author attribution remains intact. See message below. Copyright (C) 2007 Christian Pesch. All Rights Reserved. */ package slash.metamusic.itunes.gui; import com.intellij.uiDesigner.core.GridConstraints; import com.intellij.uiDesigner.core.GridLayoutManager; import com.intellij.uiDesigner.core.Spacer; import slash.metamusic.gui.BaseDialogGUI; import slash.metamusic.itunes.com.iTunesCOMSynchronizer; import javax.swing.*; import javax.swing.event.ListDataEvent; import javax.swing.event.ListDataListener; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.text.DateFormat; import java.text.MessageFormat; import java.util.Date; import java.util.ResourceBundle; /** * A small graphical user interface for the rating saving. * * @author Christian Pesch */ public class RatingSaverGUI extends BaseDialogGUI { // static { Locale.setDefault(Locale.ENGLISH); } static ResourceBundle BUNDLE = ResourceBundle.getBundle(RatingSaverGUI.class.getName()); private JPanel contentPane; private JButton buttonStart; private JButton buttonExit; private JLabel labelVersion; private JLabel labelPlaylistCount; private JLabel labelFileCount; private JLabel labelProcessedTracks; private JLabel labelFailedTracks; private JLabel labelModifiedFiles; private JLabel labelModifiedTracks; private JLabel labelRemovedTracks; private JProgressBar progressBar; private JList listMessages; private iTunesCOMSynchronizer synchronizer = new iTunesCOMSynchronizer(); private DefaultListModel listModel = new DefaultListModel(); private boolean running = false; private final Object mutex = new Object(); public void show() { connectToiTunes(); createFrame(BUNDLE.getString("title"), "/slash/metamusic/itunes/gui/RatingSaver.png", contentPane, buttonStart); buttonStart.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { onStart(); } }); buttonExit.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { onExit(); } }); progressBar.setMinimum(0); progressBar.setStringPainted(true); listMessages.setModel(listModel); listModel.addListDataListener(new ListDataListener() { public void intervalAdded(ListDataEvent e) { scrollToBottom(); } public void intervalRemoved(ListDataEvent e) { scrollToBottom(); } public void contentsChanged(ListDataEvent e) { scrollToBottom(); } }); synchronizer.setAddPlayCount(false); synchronizer.addNotifier(new UIUpdater()); openFrame(contentPane); startWaitCursor(frame.getRootPane()); synchronizer.open(); // works together with UIUpdater#opened } private void connectToiTunes() { if (!synchronizer.isiTunesSupported()) { JOptionPane.showMessageDialog(frame, BUNDLE.getString("cannot-connect-to-itunes"), BUNDLE.getString("title"), JOptionPane.ERROR_MESSAGE); System.exit(5); } } private void scrollToBottom() { // put in AWT Eventqueue to act after changes of the model SwingUtilities.invokeLater(new Runnable() { public void run() { final int lines = listModel.getSize() - 1; if (lines > 0) { // workaround to ensure visiblity on startup int count = 0; while (listMessages.getLastVisibleIndex() != lines && count++ < 10) { listMessages.ensureIndexIsVisible(lines); } } } }); } private void onStart() { synchronized (mutex) { if (running) { running = false; return; } else { running = true; } } SwingUtilities.invokeLater(new Runnable() { public void run() { startWaitCursor(frame.getRootPane()); buttonExit.setEnabled(false); buttonStart.setText(BUNDLE.getString("cancel")); } }); Thread runner = new Thread(new Runnable() { public void run() { synchronizer.start(); while (synchronizer.next()) { synchronized (mutex) { if (!running) { break; } } } synchronized (mutex) { running = false; } SwingUtilities.invokeLater(new Runnable() { public void run() { stopWaitCursor(frame.getRootPane()); buttonExit.setEnabled(true); buttonStart.setText(BUNDLE.getString("start")); } }); } }); runner.start(); } protected void onExit() { closeFrame(); synchronizer.close(); System.exit(0); } { // GUI initializer generated by IntelliJ IDEA GUI Designer // >>> IMPORTANT!! <<< // DO NOT EDIT OR ADD ANY CODE HERE! $$$setupUI$$$(); } /** * Method generated by IntelliJ IDEA GUI Designer * >>> IMPORTANT!! <<< * DO NOT edit this method OR call it in your code! * * @noinspection ALL */ private void $$$setupUI$$$() { contentPane = new JPanel(); contentPane.setLayout(new GridLayoutManager(3, 1, new Insets(10, 10, 10, 10), -1, -1)); final JPanel panel1 = new JPanel(); panel1.setLayout(new GridLayoutManager(1, 3, new Insets(0, 0, 0, 0), -1, -1)); contentPane.add(panel1, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_EAST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, 1, null, null, null, 0, false)); final Spacer spacer1 = new Spacer(); panel1.add(spacer1, new GridConstraints(0, 0, 1, 2, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false)); final JPanel panel2 = new JPanel(); panel2.setLayout(new GridLayoutManager(1, 2, new Insets(0, 0, 0, 0), -1, -1, true, false)); panel1.add(panel2, new GridConstraints(0, 2, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); buttonStart = new JButton(); buttonStart.setEnabled(false); this.$$$loadButtonText$$$(buttonStart, ResourceBundle.getBundle("slash/metamusic/itunes/gui/RatingSaverGUI").getString("start")); panel2.add(buttonStart, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); buttonExit = new JButton(); this.$$$loadButtonText$$$(buttonExit, ResourceBundle.getBundle("slash/metamusic/itunes/gui/RatingSaverGUI").getString("exit")); panel2.add(buttonExit, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); final JPanel panel3 = new JPanel(); panel3.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1)); contentPane.add(panel3, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); final JPanel panel4 = new JPanel(); panel4.setLayout(new GridLayoutManager(3, 6, new Insets(0, 0, 0, 0), -1, -1)); panel3.add(panel4, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, 1, null, null, null, 0, false)); labelVersion = new JLabel(); labelVersion.setHorizontalAlignment(2); labelVersion.setHorizontalTextPosition(2); labelVersion.setText("-"); panel4.add(labelVersion, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); final JLabel label1 = new JLabel(); label1.setInheritsPopupMenu(false); this.$$$loadLabelText$$$(label1, ResourceBundle.getBundle("slash/metamusic/itunes/gui/RatingSaverGUI").getString("processed-tracks")); panel4.add(label1, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); labelProcessedTracks = new JLabel(); labelProcessedTracks.setHorizontalAlignment(2); labelProcessedTracks.setHorizontalTextPosition(2); labelProcessedTracks.setText("-"); panel4.add(labelProcessedTracks, new GridConstraints(1, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); final JLabel label2 = new JLabel(); this.$$$loadLabelText$$$(label2, ResourceBundle.getBundle("slash/metamusic/itunes/gui/RatingSaverGUI").getString("removed-tracks")); panel4.add(label2, new GridConstraints(2, 4, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); final JLabel label3 = new JLabel(); this.$$$loadLabelText$$$(label3, ResourceBundle.getBundle("slash/metamusic/itunes/gui/RatingSaverGUI").getString("failed-tracks")); panel4.add(label3, new GridConstraints(1, 4, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); labelFailedTracks = new JLabel(); labelFailedTracks.setText("-"); panel4.add(labelFailedTracks, new GridConstraints(1, 5, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); labelRemovedTracks = new JLabel(); labelRemovedTracks.setText("-"); panel4.add(labelRemovedTracks, new GridConstraints(2, 5, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); final JLabel label4 = new JLabel(); this.$$$loadLabelText$$$(label4, ResourceBundle.getBundle("slash/metamusic/itunes/gui/RatingSaverGUI").getString("track-count")); panel4.add(label4, new GridConstraints(0, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); labelFileCount = new JLabel(); labelFileCount.setHorizontalAlignment(2); labelFileCount.setText("-"); panel4.add(labelFileCount, new GridConstraints(0, 3, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); labelPlaylistCount = new JLabel(); labelPlaylistCount.setText("-"); panel4.add(labelPlaylistCount, new GridConstraints(0, 5, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); final JLabel label5 = new JLabel(); this.$$$loadLabelText$$$(label5, ResourceBundle.getBundle("slash/metamusic/itunes/gui/RatingSaverGUI").getString("playlist-count")); panel4.add(label5, new GridConstraints(0, 4, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); final JLabel label6 = new JLabel(); this.$$$loadLabelText$$$(label6, ResourceBundle.getBundle("slash/metamusic/itunes/gui/RatingSaverGUI").getString("modified-tracks")); panel4.add(label6, new GridConstraints(1, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); labelModifiedTracks = new JLabel(); labelModifiedTracks.setText("-"); panel4.add(labelModifiedTracks, new GridConstraints(1, 3, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); final JLabel label7 = new JLabel(); this.$$$loadLabelText$$$(label7, ResourceBundle.getBundle("slash/metamusic/itunes/gui/RatingSaverGUI").getString("modified-files")); panel4.add(label7, new GridConstraints(2, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); labelModifiedFiles = new JLabel(); labelModifiedFiles.setInheritsPopupMenu(true); labelModifiedFiles.setText("-"); panel4.add(labelModifiedFiles, new GridConstraints(2, 3, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); final JLabel label8 = new JLabel(); this.$$$loadLabelText$$$(label8, ResourceBundle.getBundle("slash/metamusic/itunes/gui/RatingSaverGUI").getString("version")); panel4.add(label8, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); final JPanel panel5 = new JPanel(); panel5.setLayout(new GridLayoutManager(2, 2, new Insets(0, 0, 0, 0), -1, -1)); panel5.setVisible(true); contentPane.add(panel5, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); progressBar = new JProgressBar(); panel5.add(progressBar, new GridConstraints(1, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); final JLabel label9 = new JLabel(); this.$$$loadLabelText$$$(label9, ResourceBundle.getBundle("slash/metamusic/itunes/gui/RatingSaverGUI").getString("progress")); panel5.add(label9, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); final JLabel label10 = new JLabel(); this.$$$loadLabelText$$$(label10, ResourceBundle.getBundle("slash/metamusic/itunes/gui/RatingSaverGUI").getString("messages")); panel5.add(label10, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_NORTHWEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); final JScrollPane scrollPane1 = new JScrollPane(); panel5.add(scrollPane1, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); listMessages = new JList(); scrollPane1.setViewportView(listMessages); } /** * @noinspection ALL */ private void $$$loadLabelText$$$(JLabel component, String text) { StringBuffer result = new StringBuffer(); boolean haveMnemonic = false; char mnemonic = '\0'; int mnemonicIndex = -1; for (int i = 0; i < text.length(); i++) { if (text.charAt(i) == '&') { i++; if (i == text.length()) { break; } if (!haveMnemonic && text.charAt(i) != '&') { haveMnemonic = true; mnemonic = text.charAt(i); mnemonicIndex = result.length(); } } result.append(text.charAt(i)); } component.setText(result.toString()); if (haveMnemonic) { component.setDisplayedMnemonic(mnemonic); component.setDisplayedMnemonicIndex(mnemonicIndex); } } /** * @noinspection ALL */ private void $$$loadButtonText$$$(AbstractButton component, String text) { StringBuffer result = new StringBuffer(); boolean haveMnemonic = false; char mnemonic = '\0'; int mnemonicIndex = -1; for (int i = 0; i < text.length(); i++) { if (text.charAt(i) == '&') { i++; if (i == text.length()) { break; } if (!haveMnemonic && text.charAt(i) != '&') { haveMnemonic = true; mnemonic = text.charAt(i); mnemonicIndex = result.length(); } } result.append(text.charAt(i)); } component.setText(result.toString()); if (haveMnemonic) { component.setMnemonic(mnemonic); component.setDisplayedMnemonicIndex(mnemonicIndex); } } /** * @noinspection ALL */ public JComponent $$$getRootComponent$$$() { return contentPane; } private class UIUpdater implements iTunesCOMSynchronizer.Notifier { private Date startDate; public void opened(final String version, final String libraryPath, final int trackCount, final int playlistCount) { SwingUtilities.invokeLater(new Runnable() { public void run() { labelVersion.setText(version); labelPlaylistCount.setText(Integer.toString(playlistCount)); labelFileCount.setText(Integer.toString(trackCount)); listModel.addElement(MessageFormat.format(BUNDLE.getString("opened"), libraryPath)); buttonStart.setEnabled(true); stopWaitCursor(frame.getRootPane()); } }); } public void started(final int trackCount, final int playlistCount) { SwingUtilities.invokeLater(new Runnable() { public void run() { labelPlaylistCount.setText(Integer.toString(playlistCount)); labelFileCount.setText(Integer.toString(trackCount)); labelProcessedTracks.setText("0"); labelFailedTracks.setText("0"); labelModifiedFiles.setText("0"); labelModifiedTracks.setText("0"); labelRemovedTracks.setText("0"); startDate = new Date(); listModel.clear(); listModel.addElement(MessageFormat.format(BUNDLE.getString("started"), DateFormat.getDateTimeInstance().format(startDate))); progressBar.setMaximum(trackCount); progressBar.setValue(0); } }); } public void processing(final int processedTracks) { SwingUtilities.invokeLater(new Runnable() { public void run() { labelProcessedTracks.setText(Integer.toString(processedTracks)); progressBar.setValue(processedTracks); } }); } public void failed(final int failedTrackCount, final String location) { SwingUtilities.invokeLater(new Runnable() { public void run() { labelFailedTracks.setText(Integer.toString(failedTrackCount)); if (location != null) { listModel.addElement(MessageFormat.format(BUNDLE.getString("failed"), location)); } } }); } public void removed(final int removedTrackCount, final String location) { SwingUtilities.invokeLater(new Runnable() { public void run() { labelRemovedTracks.setText(Integer.toString(removedTrackCount)); listModel.addElement(MessageFormat.format(BUNDLE.getString("removed"), location)); } }); } public void processed(final int modifiedFileCount, final int modifiedTrackCount, final String location, final boolean fileModified, final boolean trackModified) { SwingUtilities.invokeLater(new Runnable() { public void run() { labelModifiedTracks.setText(Integer.toString(modifiedTrackCount)); labelModifiedFiles.setText(Integer.toString(modifiedFileCount)); StringBuffer buffer = new StringBuffer(); if (fileModified || trackModified) { buffer.append(BUNDLE.getString("modified")).append(" "); } if (fileModified) { buffer.append(BUNDLE.getString("file")).append(" "); } if (fileModified && trackModified) { buffer.append("& "); } if (trackModified) { buffer.append(BUNDLE.getString("track")).append(" "); } buffer.append(location); listModel.addElement(buffer.toString()); } }); } public void finished(final int modifiedFileCount, final int modifiedTrackCount, final int removedTrackCount) { SwingUtilities.invokeLater(new Runnable() { public void run() { labelModifiedTracks.setText(Integer.toString(modifiedTrackCount)); labelModifiedFiles.setText(Integer.toString(modifiedFileCount)); labelRemovedTracks.setText(Integer.toString(removedTrackCount)); Date endDate = new Date(); listModel.addElement(MessageFormat.format(BUNDLE.getString("finished"), DateFormat.getDateTimeInstance().format(endDate))); long runtime = (endDate.getTime() - startDate.getTime()) / 1000; listModel.addElement(MessageFormat.format(BUNDLE.getString("runtime"), runtime)); progressBar.setValue(progressBar.getMaximum()); } }); } } public static void main(String[] args) { setLookAndFeel(); RatingSaverGUI gui = new RatingSaverGUI(); gui.show(); } }