/* * 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.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.util.LinkedList; import java.util.List; import javax.swing.AbstractAction; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.DefaultCellEditor; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JDialog; import javax.swing.JMenuItem; import javax.swing.JPanel; 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.model.MultiTagFieldModel; import com.tulskiy.musique.gui.model.SingleTagFieldModel; import com.tulskiy.musique.gui.model.TagFieldModel; import com.tulskiy.musique.util.Util; import javax.swing.JTextPane; import javax.swing.border.LineBorder; /** * Author: Denis Tulskiy * Date: Jul 15, 2010 */ public class TracksInfoEditFieldDialog extends JDialog { private JButton cancel; private int DEFAULT_COLUMN_WIDTH = 280; public TracksInfoEditFieldDialog(final GroupTable properties, final SingleTagFieldModel tagFieldModel) { setTitle(tagFieldModel.isMultiTrackEditMode() ? "Edit multiple files" : "Edit single file"); setModal(false); JPanel singleValuePanel = new JPanel(); singleValuePanel.setLayout(new BoxLayout(singleValuePanel, BoxLayout.X_AXIS)); final JTextPane textPane = new JTextPane(); textPane.setBorder(new LineBorder(new Color(0, 0, 0))); singleValuePanel.add(textPane); JComponent tagsTable = createTable(properties, tagFieldModel); final JTabbedPane tp = new JTabbedPane(); tp.setFocusable(false); tp.addTab("Single value", singleValuePanel); tp.addTab("Multi value", tagsTable); tp.setSelectedIndex(tp.getTabCount() - 1); getContentPane().add(tp, BorderLayout.CENTER); Box b1 = new Box(BoxLayout.X_AXIS); b1.add(Box.createHorizontalGlue()); JButton update = new JButton("Update"); b1.add(update); update.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (tp.getSelectedIndex() == 0) { // update state with single value (multi value model is not taken into account) tagFieldModel.approveModel(textPane.getText()); } else { // update state with this dialog values tagFieldModel.approveModel(); } // sync parent dialog values with approved state ((TagFieldModel) properties.getModel()).refreshModel(); properties.revalidate(); properties.repaint(); setVisible(false); dispose(); properties.requestFocus(); } }); cancel = new JButton("Cancel"); cancel.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { tagFieldModel.rejectModel(); setVisible(false); dispose(); properties.requestFocus(); } }); b1.add(Box.createHorizontalStrut(5)); b1.add(cancel); b1.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 10)); getContentPane().add(b1, BorderLayout.SOUTH); setSize(600, 380); setLocationRelativeTo(SwingUtilities.windowForComponent(properties)); } private JComponent createTable(final GroupTable parent, final 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.SINGLE_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 SingleTagFieldModel) { if (((SingleTagFieldModel) tableModel).isMultiTrackEditMode()) {//.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(); } } }); 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(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 JPopupMenu buildContextMenu(final GroupTable properties) { final SingleTagFieldModel tagFieldModel = (SingleTagFieldModel) properties.getModel(); final List<Integer> selectedRows = new LinkedList<Integer>(); if (properties.getSelectedRowCount() > 0) { for (int row : properties.getSelectedRows()) { selectedRows.add(row); } } ImageIcon emptyIcon = new ImageIcon(new BufferedImage(10, 10, BufferedImage.TYPE_INT_ARGB)); final JPopupMenu menu = new JPopupMenu(); if (tagFieldModel.isMultiTrackEditMode()) { if (!selectedRows.isEmpty()) { final SingleTagFieldModel editTagFieldModel = new SingleTagFieldModel(tagFieldModel.getTrackInfoItem(), tagFieldModel.getTrackInfoItem().getTracks().get(selectedRows.get(0))); JMenuItem menuItemEdit = new JMenuItem("Edit"); menuItemEdit.setIcon(emptyIcon); menu.add(menuItemEdit).addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { TracksInfoEditFieldDialog dialog = new TracksInfoEditFieldDialog(properties, editTagFieldModel); dialog.setVisible(true); } }); } } else { JMenuItem menuItemAdd = new JMenuItem("Add"); menuItemAdd.setIcon(emptyIcon); menu.add(menuItemAdd).addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { tagFieldModel.addValue(); properties.clearSelection(); properties.revalidate(); properties.repaint(); } }); if (!selectedRows.isEmpty()) { JMenuItem menuItemRemove = new JMenuItem("Remove"); menuItemRemove.setIcon(emptyIcon); menu.add(menuItemRemove).addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { for (int row : selectedRows) { tagFieldModel.removeValue(row); } properties.clearSelection(); properties.revalidate(); properties.repaint(); } }); } } return menu; } }