source: trunk/gli/src/org/greenstone/gatherer/gui/FileAssociationDialog.java@ 9888

Last change on this file since 9888 was 9354, checked in by mdewsnip, 19 years ago

Added a couple of missing tooltips.

  • Property svn:keywords set to Author Date Id Revision
File size: 17.5 KB
Line 
1/**
2 *#########################################################################
3 *
4 * A component of the Gatherer application, part of the Greenstone digital
5 * library suite from the New Zealand Digital Library Project at the
6 * University of Waikato, New Zealand.
7 *
8 * <BR><BR>
9 *
10 * Author: John Thompson, Greenstone Digital Library, University of Waikato
11 *
12 * <BR><BR>
13 *
14 * Copyright (C) 1999 New Zealand Digital Library Project
15 *
16 * <BR><BR>
17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
22 *
23 * <BR><BR>
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * <BR><BR>
31 *
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
35 *########################################################################
36 */
37package org.greenstone.gatherer.gui;
38
39import java.awt.*;
40import java.awt.event.*;
41import java.io.File;
42import java.util.*;
43import javax.swing.*;
44import javax.swing.event.*;
45import javax.swing.filechooser.*;
46import javax.swing.table.*;
47import org.greenstone.gatherer.Configuration;
48import org.greenstone.gatherer.Dictionary;
49import org.greenstone.gatherer.Gatherer;
50import org.greenstone.gatherer.file.FileAssociationManager;
51import org.greenstone.gatherer.util.TableUtils;
52import org.greenstone.gatherer.util.Utility;
53
54/** The file association allows the entry of new file associations and the modification of existing ones.
55 * @author John Thompson, Greenstone Digital Library, University of Waikato
56 * @version 2.3
57 */
58public class FileAssociationDialog
59 extends ModalDialog {
60
61 /** The default size for the dialog. */
62 static final private Dimension SIZE = new Dimension(600, 450);
63
64 private boolean ignore = false;
65 private FileAssociationDialog self;
66 private FileAssociationManager file_association_manager;
67 private JButton add_button;
68 private JButton browse_button;
69 private JButton close_button;
70 private JButton remove_button;
71 private JButton replace_button;
72 private JTable existing_associations_table;
73 private JTextField command_field;
74 private JTextField extension_field;
75
76 /** Create a new file association dialog.
77 * @param file_association_manager A reference to the <strong>FileAssociationManager</strong> so we can determine what extensions are already associated.
78 */
79 public FileAssociationDialog(FileAssociationManager file_association_manager) {
80 super(Gatherer.g_man);
81 this.file_association_manager = file_association_manager;
82 this.self = this;
83
84 // Creation
85 setModal(true);
86 setSize(SIZE);
87 setJMenuBar(new SimpleMenuBar("fileassociations"));
88
89 JPanel content_pane = (JPanel) getContentPane();
90 content_pane.setBackground(Configuration.getColor("coloring.collection_heading_background", false));
91
92 JTextArea instructions_area = new JTextArea();
93 instructions_area.setEditable(false);
94 instructions_area.setLineWrap(true);
95 instructions_area.setRows(5);
96 instructions_area.setWrapStyleWord(true);
97 Dictionary.setText(instructions_area, "FileAssociationDialog.Instructions");
98
99 JPanel control_pane = new JPanel();
100 JLabel existing_associations_label = new JLabel();
101 existing_associations_table = new JTable(file_association_manager);
102 existing_associations_table.setAutoResizeMode(JTable.AUTO_RESIZE_NEXT_COLUMN);
103 existing_associations_table.setColumnSelectionAllowed(false);
104 existing_associations_table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
105 JPanel lower_pane = new JPanel();
106 JPanel details_pane = new JPanel();
107
108 JPanel extension_pane = new JPanel();
109 JLabel extension_label = new JLabel();
110 extension_field = new NonWhitespaceField();
111
112 JLabel command_label = new JLabel();
113 JPanel command_pane = new JPanel();
114 command_field = new JTextField();
115 browse_button = new GLIButton();
116 browse_button.setEnabled(!Utility.isMac());
117 browse_button.setMnemonic(KeyEvent.VK_B);
118
119 JPanel button_pane = new JPanel();
120
121 add_button = new GLIButton();
122 add_button.setEnabled(false);
123 add_button.setMnemonic(KeyEvent.VK_A);
124
125 replace_button = new GLIButton();
126 replace_button.setEnabled(false);
127 replace_button.setMnemonic(KeyEvent.VK_P);
128
129 remove_button = new GLIButton();
130 remove_button.setEnabled(false);
131 remove_button.setMnemonic(KeyEvent.VK_R);
132
133 close_button = new GLIButton();
134 close_button.setMnemonic(KeyEvent.VK_C);
135
136 // Connection
137 add_button.addActionListener(new AddButtonListener());
138 browse_button.addActionListener(new BrowseButtonListener());
139 close_button.addActionListener(new CloseButtonListener());
140 remove_button.addActionListener(new RemoveButtonListener());
141 replace_button.addActionListener(new ReplaceButtonListener());
142 CommandOrExtensionFieldListener coefl = new CommandOrExtensionFieldListener();
143 command_field.getDocument().addDocumentListener(coefl);
144 extension_field.getDocument().addDocumentListener(coefl);
145 coefl = null;
146 existing_associations_table.getSelectionModel().addListSelectionListener(new ExistingAssociationsTableListener());
147 Dictionary.setBoth(add_button, "FileAssociationDialog.Add", "FileAssociationDialog.Add_Tooltip");
148 if(Utility.isMac()) {
149 Dictionary.setBoth(browse_button, "FileAssociationDialog.Browse", "FileAssociationDialog.Browse_Tooltip_Mac");
150 }
151 else {
152 Dictionary.setBoth(browse_button, "FileAssociationDialog.Browse", "FileAssociationDialog.Browse_Tooltip");
153 }
154 Dictionary.setBoth(close_button, "FileAssociationDialog.Close", "FileAssociationDialog.Close_Tooltip");
155 Dictionary.setBoth(remove_button, "FileAssociationDialog.Remove", "FileAssociationDialog.Remove_Tooltip");
156 Dictionary.setBoth(replace_button, "FileAssociationDialog.Replace", "FileAssociationDialog.Replace_Tooltip");
157 Dictionary.setText(command_label, "FileAssociationDialog.Command");
158 Dictionary.setTooltip(command_field, "FileAssociationDialog.Command_Tooltip");
159 Dictionary.setText(extension_label, "FileAssociationDialog.Extension");
160 Dictionary.setTooltip(extension_field, "FileAssociationDialog.Extension_Tooltip");
161 Dictionary.setText(existing_associations_label, "FileAssociationDialog.Existing_Associations");
162 Dictionary.setText(this, "FileAssociationDialog.Title");
163
164 // Layout
165 extension_pane.setBorder(BorderFactory.createEmptyBorder(2,0,2,0));
166 extension_pane.setLayout(new BorderLayout(5,0));
167 extension_pane.add(extension_label, BorderLayout.WEST);
168 extension_pane.add(extension_field, BorderLayout.CENTER);
169
170 command_pane.setBorder(BorderFactory.createEmptyBorder(2,0,2,0));
171 command_pane.setLayout(new BorderLayout());
172 command_pane.add(command_field, BorderLayout.CENTER);
173 command_pane.add(browse_button, BorderLayout.EAST);
174
175 details_pane.setBorder(BorderFactory.createTitledBorder(Dictionary.get("FileAssociationDialog.Details")));
176 details_pane.setLayout(new GridLayout(3,1));
177 details_pane.add(extension_pane);
178 details_pane.add(command_label);
179 details_pane.add(command_pane);
180
181 lower_pane.setBorder(BorderFactory.createEmptyBorder(2,0,0,0));
182 button_pane.setLayout(new GridLayout(2,3));
183 button_pane.add(add_button);
184 button_pane.add(replace_button);
185 button_pane.add(remove_button);
186 button_pane.add(new JPanel());
187 button_pane.add(new JPanel());
188 button_pane.add(close_button);
189
190 lower_pane.setBorder(BorderFactory.createEmptyBorder(2,0,0,0));
191 lower_pane.setLayout(new BorderLayout());
192 lower_pane.add(details_pane, BorderLayout.CENTER);
193 lower_pane.add(button_pane, BorderLayout.SOUTH);
194
195 control_pane.setBorder(BorderFactory.createEmptyBorder(2,0,0,0));
196 control_pane.setLayout(new BorderLayout());
197 control_pane.add(existing_associations_label, BorderLayout.NORTH);
198 control_pane.add(new JScrollPane(existing_associations_table), BorderLayout.CENTER);
199 control_pane.add(lower_pane, BorderLayout.SOUTH);
200
201 content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
202 content_pane.setLayout(new BorderLayout());
203 content_pane.add(new JScrollPane(instructions_area), BorderLayout.NORTH);
204 content_pane.add(control_pane, BorderLayout.CENTER);
205
206 Rectangle screen = Gatherer.g_man.getBounds(null);
207 setLocation((int)(screen.getX() + (screen.getWidth() - SIZE.width) / 2), (int)(screen.getY() + (screen.getHeight() - SIZE.height) / 2));
208 screen = null;
209 }
210
211 public void destroy() {
212 // Disconnect
213 // Clean up
214 file_association_manager = null;
215 self = null;
216 }
217
218 /** 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.
219 * @param new_extension The extension code as a <strong>String</strong>.
220 */
221 public String display(String new_extension) {
222 // Clear the current selection
223 existing_associations_table.clearSelection();
224 if(new_extension != null) {
225 extension_field.setText(new_extension);
226 }
227 setVisible(true);
228 if(new_extension != null) {
229 return file_association_manager.getCommandString(new_extension);
230 }
231 return null;
232 }
233
234 protected void processWindowEvent(WindowEvent event) {
235 if(event.getID() == WindowEvent.WINDOW_ACTIVATED) {
236 TableUtils.fixColumnToPreferredWidth(existing_associations_table, 0);
237 }
238 else {
239 super.processWindowEvent(event);
240 }
241 }
242
243 private class AddButtonListener
244 implements ActionListener {
245
246 public void actionPerformed(ActionEvent event) {
247 String extension_str = extension_field.getText();
248 file_association_manager.setCommand(extension_str, command_field.getText());
249 // Select the appropriate entry in the table
250 int index = -1;
251 for(int i = 0; index == -1 && i < file_association_manager.size(); i++) {
252 if(file_association_manager.getExtension(i).equals(extension_str)) {
253 index = i;
254 }
255 }
256 if(index > -1) {
257 existing_associations_table.setRowSelectionInterval(index, index);
258 }
259 // And update buttons
260 add_button.setEnabled(false);
261 remove_button.setEnabled(true);
262 }
263 }
264
265 /** Batch filter shows only files ending in bat. Based on ImageFilter.java which is a 1.4 example used by FileChooserDemo2.java. */
266 private class BatchFileFilter
267 extends FileFilter {
268
269 /** Accept all .exe files
270 * @param file a File
271 * @return true is this file should be shown, false otherwise
272 */
273 public boolean accept(File file) {
274 return file.getName().toLowerCase().endsWith(".bat");
275 }
276
277 /** The description of this filter
278 * @return a String
279 */
280 public String getDescription() {
281 return Dictionary.get("FileAssociationDialog.Batch_File");
282 }
283 }
284
285 /** 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. */
286 private class BrowseButtonListener
287 implements ActionListener {
288 /** Open up a simple JFileChooser when the user clicks the button.
289 * @param event An <strong>ActionEvent</strong> containing information about the event.
290 */
291 public void actionPerformed(ActionEvent event) {
292 JFileChooser chooser = new JFileChooser(new File(Utility.BASE_DIR));
293 OpenCollectionDialog.disableRename(chooser);
294 chooser.setDialogTitle(Dictionary.get("FileAssociationDialog.Browse_Title"));
295 chooser.setFileFilter(new BatchFileFilter());
296 chooser.setFileFilter(new CoreObjectModelFileFilter());
297 chooser.setFileFilter(new ExecutableFileFilter());
298 chooser.setAcceptAllFileFilterUsed(true);
299 if(chooser.showOpenDialog(Gatherer.g_man) == JFileChooser.APPROVE_OPTION) {
300 command_field.setText(chooser.getSelectedFile().getAbsolutePath());
301 }
302 }
303 }
304
305 private class CloseButtonListener
306 implements ActionListener {
307 public void actionPerformed(ActionEvent event) {
308 existing_associations_table.clearSelection();
309 add_button.setEnabled(false);
310 remove_button.setEnabled(false);
311 replace_button.setEnabled(false);
312 self.dispose();
313 }
314 }
315
316 /** Command filter shows only files ending in com. Based on ImageFilter.java which is a 1.4 example used by FileChooserDemo2.java. */
317 private class CoreObjectModelFileFilter
318 extends FileFilter {
319
320 /** Accept all .exe files
321 * @param file a File
322 * @return true is this file should be shown, false otherwise
323 */
324 public boolean accept(File file) {
325 return file.getName().toLowerCase().endsWith(".com");
326 }
327
328 /** The description of this filter
329 * @return a String
330 */
331 public String getDescription() {
332 return Dictionary.get("FileAssociationDialog.Command_File");
333 }
334 }
335
336 private class CommandOrExtensionFieldListener
337 implements DocumentListener {
338 /** Gives notification that an attribute or set of attributes changed. */
339 public void changedUpdate(DocumentEvent e) {
340 changed();
341 }
342 /** Gives notification that there was an insert into the document. */
343 public void insertUpdate(DocumentEvent e) {
344 changed();
345 }
346 /** Gives notification that a portion of the document has been removed. */
347 public void removeUpdate(DocumentEvent e) {
348 changed();
349 }
350
351 private void changed() {
352 ignore = true;
353 String extension_str = extension_field.getText();
354 String command_str = command_field.getText();
355 // Determine if there is currently an association selected
356 int selected_index = -1;
357 if((selected_index = existing_associations_table.getSelectionModel().getMinSelectionIndex()) != -1) {
358 String current_extension_str = file_association_manager.getExtension(selected_index);
359 String current_command_str = file_association_manager.getCommandString(current_extension_str);
360 // What buttons are enabled depends a lot on the file extension, taken to be the 'key'
361 if(extension_str.equals(current_extension_str)) {
362 // If the extensions are the same then remove is enabled
363 remove_button.setEnabled(true);
364 // But if the command is different, then enable replace
365 if(current_command_str.length() == 0) {
366 add_button.setEnabled(true);
367 replace_button.setEnabled(false);
368 }
369 else if(!command_str.equals(current_command_str)) {
370 add_button.setEnabled(false);
371 replace_button.setEnabled(true);
372 }
373 else {
374 add_button.setEnabled(false);
375 replace_button.setEnabled(false);
376 }
377 }
378 // We can add it, but we first clear the selection
379 else {
380 existing_associations_table.clearSelection();
381 add_button.setEnabled(true);
382 remove_button.setEnabled(false);
383 replace_button.setEnabled(false);
384 }
385 }
386 // If not, we must first test if the extension is in use
387 else {
388 int index = -1;
389 for(int i = 0; index == -1 && i < file_association_manager.size(); i++) {
390 String existing_extension_str = file_association_manager.getExtension(i);
391 if(existing_extension_str.equals(extension_str)) {
392 index = i;
393 }
394 }
395 if(index != -1) {
396 // Selection that index
397 existing_associations_table.setRowSelectionInterval(index, index);
398 // Set replace and remove enabled
399 add_button.setEnabled(false);
400 remove_button.setEnabled(true);
401 replace_button.setEnabled(true);
402 }
403 // Otherwise if there is some text in both extension and command, enable add only
404 else if(extension_str.length() > 0 && command_str.length() > 0) {
405 add_button.setEnabled(true);
406 remove_button.setEnabled(false);
407 replace_button.setEnabled(false);
408 }
409 // Otherwise disable everything
410 else {
411 add_button.setEnabled(false);
412 remove_button.setEnabled(false);
413 replace_button.setEnabled(false);
414 }
415 }
416 ignore = false;
417 }
418 }
419
420 /** Executable filter shows only files ending in exe. Based on ImageFilter.java which is a 1.4 example used by FileChooserDemo2.java. */
421 private class ExecutableFileFilter
422 extends FileFilter {
423
424 /** Accept all .exe files
425 * @param file a File
426 * @return true is this file should be shown, false otherwise
427 */
428 public boolean accept(File file) {
429 return file.getName().toLowerCase().endsWith(".exe");
430 }
431
432 /** The description of this filter
433 * @return a String
434 */
435 public String getDescription() {
436 return Dictionary.get("FileAssociationDialog.Executable_File");
437 }
438 }
439
440 private class ExistingAssociationsTableListener
441 implements ListSelectionListener {
442
443 public void valueChanged(ListSelectionEvent event) {
444 if(!event.getValueIsAdjusting() && !ignore) {
445 int selected_index = -1;
446 if((selected_index = existing_associations_table.getSelectionModel().getMinSelectionIndex()) != -1) {
447 // Propagate the details of the selection down into the fields
448 String extension_str = file_association_manager.getExtension(selected_index);
449 extension_field.setText(extension_str);
450 command_field.setText(file_association_manager.getCommandString(extension_str));
451 extension_str = null;
452 remove_button.setEnabled(true);
453 }
454 else {
455 // Clear the fields
456 extension_field.setText("");
457 command_field.setText("");
458 remove_button.setEnabled(false);
459 }
460 add_button.setEnabled(false);
461 replace_button.setEnabled(false);
462 }
463 }
464 }
465
466 private class RemoveButtonListener
467 implements ActionListener {
468 public void actionPerformed(ActionEvent event) {
469 file_association_manager.setCommand(extension_field.getText(), null);
470 // And update buttons
471 add_button.setEnabled(true);
472 remove_button.setEnabled(false);
473 }
474 }
475
476 private class ReplaceButtonListener
477 implements ActionListener {
478 public void actionPerformed(ActionEvent event) {
479 file_association_manager.setCommand(extension_field.getText(), command_field.getText());
480 // And update buttons
481 replace_button.setEnabled(false);
482 }
483 }
484}
485
486
487
488
489
490
Note: See TracBrowser for help on using the repository browser.