/** *######################################################################### * * A component of the Gatherer application, part of the Greenstone digital * library suite from the New Zealand Digital Library Project at the * University of Waikato, New Zealand. * *

* * Author: John Thompson, Greenstone Digital Library, University of Waikato * *

* * Copyright (C) 1999 New Zealand Digital Library Project * *

* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 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 General Public License for more details. * *

* * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *######################################################################## */ package org.greenstone.gatherer.gui; import java.awt.*; import java.awt.event.*; import java.io.File; import java.util.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.filechooser.*; import javax.swing.table.*; import org.greenstone.gatherer.Configuration; import org.greenstone.gatherer.Dictionary; import org.greenstone.gatherer.Gatherer; import org.greenstone.gatherer.file.FileAssociationManager; import org.greenstone.gatherer.util.TableUtils; import org.greenstone.gatherer.util.Utility; /** The file association allows the entry of new file associations and the modification of existing ones. * @author John Thompson, Greenstone Digital Library, University of Waikato * @version 2.3 */ public class FileAssociationDialog extends ModalDialog { /** The default size for the dialog. */ static final private Dimension SIZE = new Dimension(600, 450); private boolean ignore = false; private FileAssociationDialog self; private FileAssociationManager file_association_manager; private JButton add_button; private JButton browse_button; private JButton close_button; private JButton remove_button; private JButton replace_button; private JTable existing_associations_table; private JTextField command_field; private JTextField extension_field; /** Create a new file association dialog. * @param file_association_manager A reference to the FileAssociationManager so we can determine what extensions are already associated. */ public FileAssociationDialog(FileAssociationManager file_association_manager) { super(Gatherer.g_man); this.file_association_manager = file_association_manager; this.self = this; this.setComponentOrientation(Dictionary.getOrientation()); // Creation setModal(true); setSize(SIZE); setTitle(Dictionary.get("FileAssociationDialog.Title")); setJMenuBar(new SimpleMenuBar("fileassociations")); JPanel content_pane = (JPanel) getContentPane(); content_pane.setBackground(Configuration.getColor("coloring.collection_heading_background", false)); content_pane.setComponentOrientation(Dictionary.getOrientation()); JTextArea instructions_area = new JTextArea(Dictionary.get("FileAssociationDialog.Instructions")); instructions_area.setEditable(false); instructions_area.setLineWrap(true); instructions_area.setRows(5); instructions_area.setWrapStyleWord(true); instructions_area.setComponentOrientation(Dictionary.getOrientation()); JPanel control_pane = new JPanel(); control_pane.setComponentOrientation(Dictionary.getOrientation()); existing_associations_table = new JTable(file_association_manager); existing_associations_table.setComponentOrientation(Dictionary.getOrientation()); existing_associations_table.setAutoResizeMode(JTable.AUTO_RESIZE_NEXT_COLUMN); existing_associations_table.setColumnSelectionAllowed(false); existing_associations_table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); JPanel lower_pane = new JPanel(); lower_pane.setComponentOrientation(Dictionary.getOrientation()); JPanel details_pane = new JPanel(); details_pane.setComponentOrientation(Dictionary.getOrientation()); JPanel extension_pane = new JPanel(); extension_pane.setComponentOrientation(Dictionary.getOrientation()); JLabel extension_label = new JLabel(Dictionary.get("FileAssociationDialog.Extension")); extension_label.setComponentOrientation(Dictionary.getOrientation()); extension_field = new NonWhitespaceField(); extension_field.setToolTipText(Dictionary.get("FileAssociationDialog.Extension_Tooltip")); JLabel command_label = new JLabel(Dictionary.get("FileAssociationDialog.Command")); command_label.setComponentOrientation(Dictionary.getOrientation()); JPanel command_pane = new JPanel(); command_pane.setComponentOrientation(Dictionary.getOrientation()); command_field = new JTextField(); command_field.setComponentOrientation(Dictionary.getOrientation()); command_field.setToolTipText(Dictionary.get("FileAssociationDialog.Command_Tooltip")); browse_button = new GLIButton(Dictionary.get("FileAssociationDialog.Browse")); browse_button.setEnabled(!Utility.isMac()); if (Utility.isMac()) { browse_button.setToolTipText(Dictionary.get("FileAssociationDialog.Browse_Tooltip_Mac")); } else { browse_button.setToolTipText(Dictionary.get("FileAssociationDialog.Browse_Tooltip")); } JPanel button_pane = new JPanel(); button_pane.setComponentOrientation(Dictionary.getOrientation()); add_button = new GLIButton(Dictionary.get("FileAssociationDialog.Add"), Dictionary.get("FileAssociationDialog.Add_Tooltip")); add_button.setEnabled(false); replace_button = new GLIButton(Dictionary.get("FileAssociationDialog.Replace"), Dictionary.get("FileAssociationDialog.Replace_Tooltip")); replace_button.setEnabled(false); remove_button = new GLIButton(Dictionary.get("FileAssociationDialog.Remove"), Dictionary.get("FileAssociationDialog.Remove_Tooltip")); remove_button.setEnabled(false); close_button = new GLIButton(Dictionary.get("FileAssociationDialog.Close"), Dictionary.get("FileAssociationDialog.Close_Tooltip")); // Connection add_button.addActionListener(new AddButtonListener()); browse_button.addActionListener(new BrowseButtonListener()); close_button.addActionListener(new CloseButtonListener()); remove_button.addActionListener(new RemoveButtonListener()); replace_button.addActionListener(new ReplaceButtonListener()); CommandOrExtensionFieldListener coefl = new CommandOrExtensionFieldListener(); command_field.getDocument().addDocumentListener(coefl); extension_field.getDocument().addDocumentListener(coefl); coefl = null; existing_associations_table.getSelectionModel().addListSelectionListener(new ExistingAssociationsTableListener()); // Layout extension_pane.setBorder(BorderFactory.createEmptyBorder(2,0,2,0)); extension_pane.setLayout(new BorderLayout(5,0)); extension_pane.add(extension_label, BorderLayout.LINE_START); extension_pane.add(extension_field, BorderLayout.CENTER); command_pane.setBorder(BorderFactory.createEmptyBorder(2,0,2,0)); command_pane.setLayout(new BorderLayout()); command_pane.add(command_field, BorderLayout.CENTER); command_pane.add(browse_button, BorderLayout.LINE_END); details_pane.setBorder(BorderFactory.createTitledBorder(Dictionary.get("FileAssociationDialog.Details"))); details_pane.setLayout(new GridLayout(3,1)); details_pane.add(extension_pane); details_pane.add(command_label); details_pane.add(command_pane); lower_pane.setBorder(BorderFactory.createEmptyBorder(2,0,0,0)); button_pane.setLayout(new GridLayout(2,3)); button_pane.add(add_button); button_pane.add(replace_button); button_pane.add(remove_button); JPanel tmp ; tmp = new JPanel(); tmp.setComponentOrientation(Dictionary.getOrientation()); button_pane.add(tmp); tmp = new JPanel(); tmp.setComponentOrientation(Dictionary.getOrientation()); button_pane.add(tmp); button_pane.add(close_button); lower_pane.setBorder(BorderFactory.createEmptyBorder(2,0,0,0)); lower_pane.setLayout(new BorderLayout()); lower_pane.add(details_pane, BorderLayout.CENTER); lower_pane.add(button_pane, BorderLayout.SOUTH); control_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0)); control_pane.setLayout(new BorderLayout()); JScrollPane scrol_tmp; scrol_tmp = new JScrollPane(existing_associations_table); scrol_tmp.setComponentOrientation(Dictionary.getOrientation()); control_pane.add(scrol_tmp, BorderLayout.CENTER); control_pane.add(lower_pane, BorderLayout.SOUTH); content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); content_pane.setLayout(new BorderLayout()); scrol_tmp = new JScrollPane(instructions_area); scrol_tmp.setComponentOrientation(Dictionary.getOrientation()); content_pane.add(scrol_tmp, BorderLayout.NORTH); content_pane.add(control_pane, BorderLayout.CENTER); Rectangle screen = Gatherer.g_man.getBounds(null); setLocation((int)(screen.getX() + (screen.getWidth() - SIZE.width) / 2), (int)(screen.getY() + (screen.getHeight() - SIZE.height) / 2)); screen = null; } public void destroy() { // Disconnect // Clean up file_association_manager = null; self = null; } /** Redisplay the dialog, ensuring that the details (or lack thereof) for a certain extension is apparent. In fact if an extension is provided force the user to add it or cancel. * @param new_extension The extension code as a String. */ public String display(String new_extension) { // Clear the current selection existing_associations_table.clearSelection(); if(new_extension != null) { extension_field.setText(new_extension); } setVisible(true); if(new_extension != null) { return file_association_manager.getCommandString(new_extension); } return null; } protected void processWindowEvent(WindowEvent event) { if(event.getID() == WindowEvent.WINDOW_ACTIVATED) { TableUtils.fixColumnToPreferredWidth(existing_associations_table, 0); } else { super.processWindowEvent(event); } } private class AddButtonListener implements ActionListener { public void actionPerformed(ActionEvent event) { String extension_str = extension_field.getText(); file_association_manager.setCommand(extension_str, command_field.getText()); // Select the appropriate entry in the table int index = -1; for(int i = 0; index == -1 && i < file_association_manager.size(); i++) { if(file_association_manager.getExtension(i).equals(extension_str)) { index = i; } } if(index > -1) { existing_associations_table.setRowSelectionInterval(index, index); } // And update buttons add_button.setEnabled(false); remove_button.setEnabled(true); } } /** Batch filter shows only files ending in bat. Based on ImageFilter.java which is a 1.4 example used by FileChooserDemo2.java. */ private class BatchFileFilter extends FileFilter { /** Accept all .exe files * @param file a File * @return true is this file should be shown, false otherwise */ public boolean accept(File file) { return file.getName().toLowerCase().endsWith(".bat"); } /** The description of this filter * @return a String */ public String getDescription() { return Dictionary.get("FileAssociationDialog.Batch_File"); } } /** Whenever the user clicks the browse button, we should open up a file browser to allow them to select an executable file from somewhere in the file system. */ private class BrowseButtonListener implements ActionListener { /** Open up a simple JFileChooser when the user clicks the button. * @param event An ActionEvent containing information about the event. */ public void actionPerformed(ActionEvent event) { JFileChooser chooser = new JFileChooser(new File(Gatherer.getGLIUserDirectoryPath())); GUIUtils.disableRename(chooser); chooser.setDialogTitle(Dictionary.get("FileAssociationDialog.Browse_Title")); chooser.setFileFilter(new BatchFileFilter()); chooser.setFileFilter(new CoreObjectModelFileFilter()); chooser.setFileFilter(new ExecutableFileFilter()); chooser.setAcceptAllFileFilterUsed(true); if(chooser.showOpenDialog(Gatherer.g_man) == JFileChooser.APPROVE_OPTION) { command_field.setText(chooser.getSelectedFile().getAbsolutePath()); } } } private class CloseButtonListener implements ActionListener { public void actionPerformed(ActionEvent event) { existing_associations_table.clearSelection(); add_button.setEnabled(false); remove_button.setEnabled(false); replace_button.setEnabled(false); self.dispose(); } } /** Command filter shows only files ending in com. Based on ImageFilter.java which is a 1.4 example used by FileChooserDemo2.java. */ private class CoreObjectModelFileFilter extends FileFilter { /** Accept all .exe files * @param file a File * @return true is this file should be shown, false otherwise */ public boolean accept(File file) { return file.getName().toLowerCase().endsWith(".com"); } /** The description of this filter * @return a String */ public String getDescription() { return Dictionary.get("FileAssociationDialog.Command_File"); } } private class CommandOrExtensionFieldListener implements DocumentListener { /** Gives notification that an attribute or set of attributes changed. */ public void changedUpdate(DocumentEvent e) { changed(); } /** Gives notification that there was an insert into the document. */ public void insertUpdate(DocumentEvent e) { changed(); } /** Gives notification that a portion of the document has been removed. */ public void removeUpdate(DocumentEvent e) { changed(); } private void changed() { ignore = true; String extension_str = extension_field.getText(); String command_str = command_field.getText(); // Determine if there is currently an association selected int selected_index = -1; if((selected_index = existing_associations_table.getSelectionModel().getMinSelectionIndex()) != -1) { String current_extension_str = file_association_manager.getExtension(selected_index); String current_command_str = file_association_manager.getCommandString(current_extension_str); // What buttons are enabled depends a lot on the file extension, taken to be the 'key' if(extension_str.equals(current_extension_str)) { // If the extensions are the same then remove is enabled remove_button.setEnabled(true); // But if the command is different, then enable replace if(current_command_str.length() == 0) { add_button.setEnabled(true); replace_button.setEnabled(false); } else if(!command_str.equals(current_command_str)) { add_button.setEnabled(false); replace_button.setEnabled(true); } else { add_button.setEnabled(false); replace_button.setEnabled(false); } } // We can add it, but we first clear the selection else { existing_associations_table.clearSelection(); add_button.setEnabled(true); remove_button.setEnabled(false); replace_button.setEnabled(false); } } // If not, we must first test if the extension is in use else { int index = -1; for(int i = 0; index == -1 && i < file_association_manager.size(); i++) { String existing_extension_str = file_association_manager.getExtension(i); if(existing_extension_str.equals(extension_str)) { index = i; } } if(index != -1) { // Selection that index existing_associations_table.setRowSelectionInterval(index, index); // Set replace and remove enabled add_button.setEnabled(false); remove_button.setEnabled(true); replace_button.setEnabled(true); } // Otherwise if there is some text in both extension and command, enable add only else if(extension_str.length() > 0 && command_str.length() > 0) { add_button.setEnabled(true); remove_button.setEnabled(false); replace_button.setEnabled(false); } // Otherwise disable everything else { add_button.setEnabled(false); remove_button.setEnabled(false); replace_button.setEnabled(false); } } ignore = false; } } /** Executable filter shows only files ending in exe. Based on ImageFilter.java which is a 1.4 example used by FileChooserDemo2.java. */ private class ExecutableFileFilter extends FileFilter { /** Accept all .exe files * @param file a File * @return true is this file should be shown, false otherwise */ public boolean accept(File file) { return file.getName().toLowerCase().endsWith(".exe"); } /** The description of this filter * @return a String */ public String getDescription() { return Dictionary.get("FileAssociationDialog.Executable_File"); } } private class ExistingAssociationsTableListener implements ListSelectionListener { public void valueChanged(ListSelectionEvent event) { if(!event.getValueIsAdjusting() && !ignore) { int selected_index = -1; if((selected_index = existing_associations_table.getSelectionModel().getMinSelectionIndex()) != -1) { // Propagate the details of the selection down into the fields String extension_str = file_association_manager.getExtension(selected_index); extension_field.setText(extension_str); command_field.setText(file_association_manager.getCommandString(extension_str)); extension_str = null; remove_button.setEnabled(true); } else { // Clear the fields extension_field.setText(""); command_field.setText(""); remove_button.setEnabled(false); } add_button.setEnabled(false); replace_button.setEnabled(false); } } } private class RemoveButtonListener implements ActionListener { public void actionPerformed(ActionEvent event) { file_association_manager.setCommand(extension_field.getText(), null); // And update buttons add_button.setEnabled(true); remove_button.setEnabled(false); } } private class ReplaceButtonListener implements ActionListener { public void actionPerformed(ActionEvent event) { file_association_manager.setCommand(extension_field.getText(), command_field.getText()); // And update buttons replace_button.setEnabled(false); } } }