Package com.tulskiy.musique.gui.dialogs

Source Code of com.tulskiy.musique.gui.dialogs.TracksInfoDialog

/*
* Copyright (c) 2008, 2009, 2010 Denis Tulskiy
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with this work.  If not, see <http://www.gnu.org/licenses/>.
*/

package com.tulskiy.musique.gui.dialogs;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.DefaultCellEditor;
import javax.swing.ImageIcon;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;

import com.tulskiy.musique.gui.components.GroupTable;
import com.tulskiy.musique.gui.cpp.TrackInfoItemSelection;
import com.tulskiy.musique.gui.model.FileInfoModel;
import com.tulskiy.musique.gui.model.MultiTagFieldModel;
import com.tulskiy.musique.gui.model.SingleTagFieldModel;
import com.tulskiy.musique.gui.model.Tools;
import com.tulskiy.musique.gui.model.TrackInfoItem;
import com.tulskiy.musique.gui.playlist.PlaylistTable;
import com.tulskiy.musique.playlist.Track;
import com.tulskiy.musique.playlist.TrackData;
import com.tulskiy.musique.system.TrackIO;
import com.tulskiy.musique.util.Util;

/**
* Author: Denis Tulskiy
* Date: Jul 15, 2010
*/
public class TracksInfoDialog extends JDialog {
    private JButton cancel;
    private PlaylistTable parent;
    private int DEFAULT_COLUMN_WIDTH = 430;

    public TracksInfoDialog(final PlaylistTable parent, final List<Track> tracks) {
        this.parent = parent;
        setTitle("Properties");
        setModal(false);

        final MultiTagFieldModel tagFieldsModel = new MultiTagFieldModel(tracks);
        final JComponent tagsTable = createTable(tagFieldsModel);
        final JComponent propsTable = createTable(new FileInfoModel(tracks));

        JTabbedPane tp = new JTabbedPane();
        tp.setFocusable(false);
        tp.addTab("Metadata", tagsTable);
        tp.addTab("Properties", propsTable);

        add(tp, BorderLayout.CENTER);

        Box b1 = new Box(BoxLayout.X_AXIS);
        b1.add(Box.createHorizontalStrut(10));
        final JButton tools = new JButton("Tools");
        b1.add(tools);
        tools.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                final JPopupMenu menu = new JPopupMenu();

                JMenuItem menuItemEdit = new JMenuItem("Auto track number");
                menu.add(menuItemEdit).addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
              Tools.autoTrackNumber(tagFieldsModel);
              tagFieldsModel.sort();
             
                tagsTable.revalidate();
                tagsTable.repaint();
            }
              });
               
                menu.show(tools, 0, tools.getBounds().height);
            }
        });
        b1.add(Box.createHorizontalGlue());
        JButton write = new JButton("Write");
        b1.add(write);
        write.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
              tagFieldsModel.approveModel();
                writeTracks(tracks);
            }
        });
        cancel = new JButton("Cancel");
        cancel.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
              tagFieldsModel.rejectModel();
              setVisible(false);
                dispose();
                parent.requestFocus();
            }
        });

        b1.add(Box.createHorizontalStrut(5));
        b1.add(cancel);
        b1.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 10));

        add(b1, BorderLayout.SOUTH);

        setSize(600, 380);
        setLocationRelativeTo(SwingUtilities.windowForComponent(parent));
    }

    private void writeTracks(final List<Track> tracks) {
        ProgressDialog dialog = new ProgressDialog(this, "Writing tags");
        dialog.show(new Task() {
            String status;
            boolean abort = false;
            public int processed;

            @Override
            public boolean isIndeterminate() {
                return false;
            }

            @Override
            public float getProgress() {
                return (float) processed / tracks.size();
            }

            @Override
            public String getStatus() {
                return "Writing Tags to: " + status;
            }

            @Override
            public void abort() {
                abort = true;
            }

            @Override
            public void start() {
                HashMap<File, ArrayList<Track>> cues = new HashMap<File, ArrayList<Track>>();

                for (Track track : tracks) {
                  TrackData trackData = track.getTrackData();
                    if (!trackData.isFile()) {
                        processed++;
                        continue;
                    }

                    if (abort)
                        break;

                    if (trackData.isCue()) {
                        File file;
                        if (trackData.isCueEmbedded()) {
                            file = trackData.getFile();
                        } else {
                            file = new File(trackData.getCueLocation());
                        }

                        if (!cues.containsKey(file)) {
                            cues.put(file, new ArrayList<Track>());
                        }

                        cues.get(file).add(track);
                        continue;
                    }
                    status = trackData.getFile().getName();
                    TrackIO.write(track);
                    processed++;
                }

                // now let's write cue files
                // not implemented for now
//                CUEWriter writer = new CUEWriter();
//                for (File file : cues.keySet()) {
//                    status = file.getName();
//                    writer.write(file, cues.get(file));
//                }

                parent.getPlaylist().firePlaylistChanged();
                setVisible(false);
                dispose();
                parent.requestFocus();
            }
        });
    }

    private JComponent createTable(TableModel model) {
        final GroupTable table = new GroupTable() {
            public Component prepareRenderer(final TableCellRenderer renderer,
                                             final int row, final int column) {
                final Component prepareRenderer = super
                        .prepareRenderer(renderer, row, column);
                final TableColumn tableColumn = getColumnModel().getColumn(column);

                tableColumn.setPreferredWidth(Math.max(
                        prepareRenderer.getPreferredSize().width + 20,
                        tableColumn.getPreferredWidth()));

                tableColumn.setPreferredWidth(Math.max(
                        DEFAULT_COLUMN_WIDTH,
                        tableColumn.getPreferredWidth()));

                return prepareRenderer;
            }
        };
        table.setModel(model);
        table.setFont(table.getFont().deriveFont(11f));

        table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        table.getColumn("Key").setMaxWidth(120);

        table.setShowVerticalLines(true);
        table.setIntercellSpacing(new Dimension(1, 1));
        table.setGridColor(Color.lightGray);
        table.getSelectionModel().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
        table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
        final JTextField editor = new JTextField();
        table.setDefaultEditor(Object.class, new DefaultCellEditor(editor) {
            @Override
            public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
                TableModel tableModel = table.getModel();
                if (tableModel instanceof MultiTagFieldModel) {
                    if (((MultiTagFieldModel) tableModel).getTrackInfoItems().get(row).isMultiple()) {
                        value = "";
                    }
                }
                JTextField c = (JTextField) super.getTableCellEditorComponent(table, value, isSelected, row, column);
                c.setBorder(BorderFactory.createEmptyBorder());
                c.setFont(table.getFont());
                c.selectAll();
                return c;
            }

            @Override
            public void cancelCellEditing() {
                super.cancelCellEditing();
            }

            @Override
            protected void fireEditingStopped() {
                TableModel tableModel = table.getModel();
                if (tableModel instanceof MultiTagFieldModel) {
                    String value = (String) table.getCellEditor().getCellEditorValue();
                    if (Util.isEmpty(value) && ((MultiTagFieldModel) tableModel).getTrackInfoItems().get(table.getEditingRow()).isMultiple()) {
                        super.fireEditingCanceled();
                        return;
                    }
                }

                super.fireEditingStopped();
            }
        });
        table.addKeyboardAction(KeyStroke.getKeyStroke("ENTER"), "startEditing", new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                table.editCellAt(table.getSelectedRow(), 1);
                editor.requestFocusInWindow();
            }
        });
        table.addKeyboardAction(KeyStroke.getKeyStroke("DELETE"), "clearCell", new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                table.getModel().setValueAt("", table.getSelectedRow(), 1);
                table.repaint();
            }
        });
        table.addKeyboardAction(KeyStroke.getKeyStroke("ESCAPE"), "exitOrStop", new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (table.isEditing()) {
                    table.getCellEditor().cancelCellEditing();
                } else {
                    cancel.doClick();
                }
            }
        });
        editor.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                if (table.isEditing() && (
                        e.getKeyCode() == KeyEvent.VK_DOWN ||
                        e.getKeyCode() == KeyEvent.VK_UP)) {
                    table.getCellEditor().cancelCellEditing();
                }
            }
        });
       
        buildActions(table);
       
        table.addMouseListener(new MouseAdapter() {
     
      @Override
      public void mouseReleased(MouseEvent e) {
        show(e);
      }
     
      @Override
      public void mousePressed(MouseEvent e) {
        show(e);
      }

            public void show(MouseEvent e) {
                if (e.isPopupTrigger()) {
                  int index = table.rowAtPoint(e.getPoint());
                  if (index != -1) {
                        if (!table.isRowSelected(index)) {
                          table.setRowSelectionInterval(index, index);
                        }
                      JPopupMenu contextMenu = buildContextMenu(parent, table);
                      contextMenu.show(e.getComponent(), e.getX(), e.getY());
                  }
                }
            }
    });

        JScrollPane scrollPane = new JScrollPane(table);
        scrollPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));

        return scrollPane;
    }

    private MultiTagFieldModel getTagFieldModel(final GroupTable properties) {
      return (MultiTagFieldModel) properties.getModel();
    }

    private List<TrackInfoItem> getSelectedItems(final GroupTable properties) {
      final List<TrackInfoItem> trackInfoItemsSelected = new LinkedList<TrackInfoItem>();

      if (properties.getSelectedRowCount() > 0) {
        for (int row : properties.getSelectedRows()) {
          trackInfoItemsSelected.add(getTagFieldModel(properties).getTrackInfoItems().get(row));
        }
      }
     
      return trackInfoItemsSelected;
    }
   
    private void buildActions(final GroupTable table) {
        ActionMap aMap = table.getActionMap();
        InputMap iMap = table.getInputMap(table.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);

        aMap.put("edit", new AbstractAction("Edit") {
            @Override
            public void actionPerformed(ActionEvent e) {
              List<TrackInfoItem> selectedItems = getSelectedItems(table);
              TrackInfoItem firstItem = selectedItems.get(0);
              if (!selectedItems.isEmpty()) {
              final SingleTagFieldModel tagFieldModel = firstItem.getTracks().size() == 1 ?
                  new SingleTagFieldModel(firstItem, firstItem.getTracks().get(0)) :
                   new SingleTagFieldModel(firstItem);
          TracksInfoEditFieldDialog dialog = new TracksInfoEditFieldDialog(table, tagFieldModel);
          dialog.setVisible(true);
              }
            }
        });

        aMap.put("capitalize", new AbstractAction("Capitalize") {
            @Override
            public void actionPerformed(ActionEvent e) {
              List<TrackInfoItem> selectedItems = getSelectedItems(table);
              if (!selectedItems.isEmpty()) {
                  Tools.capitalize(selectedItems);
                  table.revalidate();
                  table.repaint();
              }
            }
        });

        aMap.put("cut", new AbstractAction("Cut fields") {
            @Override
            public void actionPerformed(ActionEvent e) {
              List<TrackInfoItem> selectedItems = getSelectedItems(table);
              if (!selectedItems.isEmpty()) {
          TrackInfoItemSelection selection = new TrackInfoItemSelection(selectedItems);
          getToolkit().getSystemClipboard().setContents(selection, selection);
          getTagFieldModel(table).removeTrackInfoItems(selectedItems);
          refreshTable(table);
              }
            }
        });

        aMap.put("copy", new AbstractAction("Copy fields") {
            @Override
            public void actionPerformed(ActionEvent e) {
              List<TrackInfoItem> selectedItems = getSelectedItems(table);
              if (!selectedItems.isEmpty()) {
          TrackInfoItemSelection selection = new TrackInfoItemSelection(selectedItems);
          getToolkit().getSystemClipboard().setContents(selection, selection);
              }
            }
        });

        aMap.put("paste", new AbstractAction("Paste fields") {
            @Override
            public void actionPerformed(ActionEvent e) {
        List<TrackInfoItem> items = null;
        try {
          items = (List<TrackInfoItem>) getToolkit().getSystemClipboard().getContents(null).
              getTransferData(TrackInfoItemSelection.objectFlavor);
        }
        catch (IOException ioe) {
          // ignore, treating as the clipboard is empty
        }
        catch (UnsupportedFlavorException ufe) {
          // ignore since we already checked at menu construction that flavor is supported
        }
        if (items != null) {
          MultiTagFieldModel model = getTagFieldModel(table);
          model.mergeTrackInfoItems(items);
          model.sort();
          refreshTable(table);
        }
            }
        });

        aMap.put("add", new AbstractAction("Add") {
            @Override
            public void actionPerformed(ActionEvent e) {
        TracksInfoAddFieldDialog dialog = new TracksInfoAddFieldDialog(table, getTagFieldModel(table));
        dialog.setVisible(true);
        refreshTable(table);
            }
        });

        aMap.put("remove", new AbstractAction("Remove") {
            @Override
            public void actionPerformed(ActionEvent e) {
              List<TrackInfoItem> selectedItems = getSelectedItems(table);
              if (!selectedItems.isEmpty()) {
          getTagFieldModel(table).removeTrackInfoItems(selectedItems);
          refreshTable(table);
              }
            }
        });

        iMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_X,
            ActionEvent.CTRL_MASK + ActionEvent.SHIFT_MASK), "cut");
        iMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_C,
            ActionEvent.CTRL_MASK + ActionEvent.SHIFT_MASK), "copy");
        iMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_V,
            ActionEvent.CTRL_MASK + ActionEvent.SHIFT_MASK), "paste");
        iMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_N,
            ActionEvent.CTRL_MASK), "add");
    }

    private JPopupMenu buildContextMenu(final PlaylistTable playlist, final GroupTable properties) {
      boolean isAnyRowSelected = properties.getSelectedRowCount() > 0;
        Transferable clipboardContent = getToolkit().getSystemClipboard().getContents(null);
     
      ImageIcon emptyIcon = new ImageIcon(new BufferedImage(10, 10, BufferedImage.TYPE_INT_ARGB));

        final JPopupMenu menu = new JPopupMenu();

        JMenuItem menuItemEdit = new JMenuItem("Edit");
        menuItemEdit.setIcon(emptyIcon);
        menuItemEdit.setEnabled(isAnyRowSelected);
        menu.add(menuItemEdit).addActionListener(properties.getActionMap().get("edit"));

        JMenuItem menuItemCapitalize = new JMenuItem("Capitalize");
        menuItemCapitalize.setIcon(emptyIcon);
        menuItemCapitalize.setEnabled(isAnyRowSelected);
        menu.add(menuItemCapitalize).addActionListener(properties.getActionMap().get("capitalize"));
       
        menu.addSeparator();

        JMenuItem menuItemCut = new JMenuItem("Cut fields");
        menuItemCut.setIcon(emptyIcon);
        menuItemCut.setEnabled(isAnyRowSelected);
        menuItemCut.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X,
            ActionEvent.CTRL_MASK + ActionEvent.SHIFT_MASK));
        menu.add(menuItemCut).addActionListener(properties.getActionMap().get("cut"));

        JMenuItem menuItemCopy = new JMenuItem("Copy fields");
        menuItemCopy.setIcon(emptyIcon);
        menuItemCopy.setEnabled(isAnyRowSelected);
        menuItemCopy.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C,
            ActionEvent.CTRL_MASK + ActionEvent.SHIFT_MASK));
        menu.add(menuItemCopy).addActionListener(properties.getActionMap().get("copy"));

        JMenuItem menuItemPaste = new JMenuItem("Paste fields");
        menuItemPaste.setIcon(emptyIcon);
        menuItemPaste.setEnabled(clipboardContent != null && clipboardContent.isDataFlavorSupported(TrackInfoItemSelection.objectFlavor));
        menuItemPaste.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V,
            ActionEvent.CTRL_MASK + ActionEvent.SHIFT_MASK));
        menu.add(menuItemPaste).addActionListener(properties.getActionMap().get("paste"));

        menu.addSeparator();

        JMenuItem menuItemAdd = new JMenuItem("Add");
        menuItemAdd.setIcon(emptyIcon);
        menuItemAdd.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N,
            ActionEvent.CTRL_MASK));
        menu.add(menuItemAdd).addActionListener(properties.getActionMap().get("add"));
       
        JMenuItem menuItemRemove = new JMenuItem("Remove");
        menuItemRemove.setIcon(emptyIcon);
        menuItemRemove.setEnabled(isAnyRowSelected);
        menu.add(menuItemRemove).addActionListener(properties.getActionMap().get("remove"));
       
        return menu;
    }
   
    private void refreshTable(JTable table) {
      table.clearSelection();
      table.revalidate();
      table.repaint();
    }

}
TOP

Related Classes of com.tulskiy.musique.gui.dialogs.TracksInfoDialog

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.