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

Last change on this file since 18376 was 18370, checked in by kjdon, 15 years ago

committed code submitted by Amin Hedjazi for making the GLI right to left. I worked on this code on the rtl-gli branch, then merged the branch back to the trunk at revision 18368. The branch code was slightly different in a couple of places where it shouldn't have been. So don't use the branch code next time. Start a new branch.

  • Property svn:keywords set to Author Date Id Revision
File size: 18.2 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 this.setComponentOrientation(Dictionary.getOrientation());
84 // Creation
85 setModal(true);
86 setSize(SIZE);
87 setTitle(Dictionary.get("FileAssociationDialog.Title"));
88 setJMenuBar(new SimpleMenuBar("fileassociations"));
89
90 JPanel content_pane = (JPanel) getContentPane();
91 content_pane.setBackground(Configuration.getColor("coloring.collection_heading_background", false));
92
93 JTextArea instructions_area = new JTextArea(Dictionary.get("FileAssociationDialog.Instructions"));
94 instructions_area.setEditable(false);
95 instructions_area.setLineWrap(true);
96 instructions_area.setRows(5);
97 instructions_area.setWrapStyleWord(true);
98
99 JPanel control_pane = new JPanel();
100 existing_associations_table = new JTable(file_association_manager);
101 existing_associations_table.setAutoResizeMode(JTable.AUTO_RESIZE_NEXT_COLUMN);
102 existing_associations_table.setColumnSelectionAllowed(false);
103 existing_associations_table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
104 JPanel lower_pane = new JPanel();
105 JPanel details_pane = new JPanel();
106
107 JPanel extension_pane = new JPanel();
108 JLabel extension_label = new JLabel(Dictionary.get("FileAssociationDialog.Extension"));
109 extension_field = new NonWhitespaceField();
110 extension_field.setToolTipText(Dictionary.get("FileAssociationDialog.Extension_Tooltip"));
111
112 JLabel command_label = new JLabel(Dictionary.get("FileAssociationDialog.Command"));
113 JPanel command_pane = new JPanel();
114 command_field = new JTextField();
115 command_field.setToolTipText(Dictionary.get("FileAssociationDialog.Command_Tooltip"));
116 browse_button = new GLIButton(Dictionary.get("FileAssociationDialog.Browse"));
117 browse_button.setEnabled(!Utility.isMac());
118 if (Utility.isMac()) {
119 browse_button.setToolTipText(Dictionary.get("FileAssociationDialog.Browse_Tooltip_Mac"));
120 } else {
121 browse_button.setToolTipText(Dictionary.get("FileAssociationDialog.Browse_Tooltip"));
122 }
123
124
125 JPanel button_pane = new JPanel();
126
127 add_button = new GLIButton(Dictionary.get("FileAssociationDialog.Add"), Dictionary.get("FileAssociationDialog.Add_Tooltip"));
128 add_button.setEnabled(false);
129
130 replace_button = new GLIButton(Dictionary.get("FileAssociationDialog.Replace"), Dictionary.get("FileAssociationDialog.Replace_Tooltip"));
131 replace_button.setEnabled(false);
132
133 remove_button = new GLIButton(Dictionary.get("FileAssociationDialog.Remove"), Dictionary.get("FileAssociationDialog.Remove_Tooltip"));
134 remove_button.setEnabled(false);
135
136 close_button = new GLIButton(Dictionary.get("FileAssociationDialog.Close"), Dictionary.get("FileAssociationDialog.Close_Tooltip"));
137
138 // Connection
139 add_button.addActionListener(new AddButtonListener());
140 browse_button.addActionListener(new BrowseButtonListener());
141 close_button.addActionListener(new CloseButtonListener());
142 remove_button.addActionListener(new RemoveButtonListener());
143 replace_button.addActionListener(new ReplaceButtonListener());
144 CommandOrExtensionFieldListener coefl = new CommandOrExtensionFieldListener();
145 command_field.getDocument().addDocumentListener(coefl);
146 extension_field.getDocument().addDocumentListener(coefl);
147 coefl = null;
148 existing_associations_table.getSelectionModel().addListSelectionListener(new ExistingAssociationsTableListener());
149
150 // Layout
151 extension_pane.setBorder(BorderFactory.createEmptyBorder(2,0,2,0));
152 extension_pane.setLayout(new BorderLayout(5,0));
153 extension_pane.add(extension_label, BorderLayout.LINE_START);
154 extension_pane.add(extension_field, BorderLayout.CENTER);
155
156 command_pane.setBorder(BorderFactory.createEmptyBorder(2,0,2,0));
157 command_pane.setLayout(new BorderLayout());
158 command_pane.add(command_field, BorderLayout.CENTER);
159 command_pane.add(browse_button, BorderLayout.LINE_END);
160
161 details_pane.setBorder(BorderFactory.createTitledBorder(Dictionary.get("FileAssociationDialog.Details")));
162 details_pane.setLayout(new GridLayout(3,1));
163 details_pane.add(extension_pane);
164 details_pane.add(command_label);
165 details_pane.add(command_pane);
166
167 lower_pane.setBorder(BorderFactory.createEmptyBorder(2,0,0,0));
168 button_pane.setLayout(new GridLayout(2,3));
169 button_pane.add(add_button);
170 button_pane.add(replace_button);
171 button_pane.add(remove_button);
172 button_pane.add(new JPanel());
173 button_pane.add(new JPanel());
174 button_pane.add(close_button);
175
176 lower_pane.setBorder(BorderFactory.createEmptyBorder(2,0,0,0));
177 lower_pane.setLayout(new BorderLayout());
178 lower_pane.add(details_pane, BorderLayout.CENTER);
179 lower_pane.add(button_pane, BorderLayout.SOUTH);
180
181 control_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
182 control_pane.setLayout(new BorderLayout());
183 JScrollPane scrol_tmp;
184 scrol_tmp = new JScrollPane(existing_associations_table);
185 scrol_tmp.setComponentOrientation(Dictionary.getOrientation());
186 control_pane.add(scrol_tmp, BorderLayout.CENTER);
187 control_pane.add(lower_pane, BorderLayout.SOUTH);
188
189 content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
190 content_pane.setLayout(new BorderLayout());
191 scrol_tmp = new JScrollPane(instructions_area);
192 scrol_tmp.setComponentOrientation(Dictionary.getOrientation());
193 content_pane.add(scrol_tmp, BorderLayout.NORTH);
194 content_pane.add(control_pane, BorderLayout.CENTER);
195
196 Rectangle screen = Gatherer.g_man.getBounds(null);
197 setLocation((int)(screen.getX() + (screen.getWidth() - SIZE.width) / 2), (int)(screen.getY() + (screen.getHeight() - SIZE.height) / 2));
198 screen = null;
199
200 //RTL
201 content_pane.setComponentOrientation(Dictionary.getOrientation());
202 instructions_area.setComponentOrientation(Dictionary.getOrientation());
203 control_pane.setComponentOrientation(Dictionary.getOrientation());
204 existing_associations_table.setComponentOrientation(Dictionary.getOrientation());
205 lower_pane.setComponentOrientation(Dictionary.getOrientation());
206 details_pane.setComponentOrientation(Dictionary.getOrientation());
207 extension_pane.setComponentOrientation(Dictionary.getOrientation());
208 extension_label.setComponentOrientation(Dictionary.getOrientation());
209 extension_field.setComponentOrientation(Dictionary.getOrientation());
210 command_label.setComponentOrientation(Dictionary.getOrientation());
211 command_pane.setComponentOrientation(Dictionary.getOrientation());
212 //end
213 }
214
215 public void destroy() {
216 // Disconnect
217 // Clean up
218 file_association_manager = null;
219 self = null;
220 }
221
222 /** 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.
223 * @param new_extension The extension code as a <strong>String</strong>.
224 */
225 public String display(String new_extension) {
226 // Clear the current selection
227 existing_associations_table.clearSelection();
228 if(new_extension != null) {
229 extension_field.setText(new_extension);
230 }
231 setVisible(true);
232 if(new_extension != null) {
233 return file_association_manager.getCommandString(new_extension);
234 }
235 return null;
236 }
237
238 protected void processWindowEvent(WindowEvent event) {
239 if(event.getID() == WindowEvent.WINDOW_ACTIVATED) {
240 TableUtils.fixColumnToPreferredWidth(existing_associations_table, 0);
241 }
242 else {
243 super.processWindowEvent(event);
244 }
245 }
246
247 private class AddButtonListener
248 implements ActionListener {
249
250 public void actionPerformed(ActionEvent event) {
251 String extension_str = extension_field.getText();
252 file_association_manager.setCommand(extension_str, command_field.getText());
253 // Select the appropriate entry in the table
254 int index = -1;
255 for(int i = 0; index == -1 && i < file_association_manager.size(); i++) {
256 if(file_association_manager.getExtension(i).equals(extension_str)) {
257 index = i;
258 }
259 }
260 if(index > -1) {
261 existing_associations_table.setRowSelectionInterval(index, index);
262 }
263 // And update buttons
264 add_button.setEnabled(false);
265 remove_button.setEnabled(true);
266 }
267 }
268
269 /** Batch filter shows only files ending in bat. Based on ImageFilter.java which is a 1.4 example used by FileChooserDemo2.java. */
270 private class BatchFileFilter
271 extends FileFilter {
272
273 /** Accept all .exe files
274 * @param file a File
275 * @return true is this file should be shown, false otherwise
276 */
277 public boolean accept(File file) {
278 return file.getName().toLowerCase().endsWith(".bat");
279 }
280
281 /** The description of this filter
282 * @return a String
283 */
284 public String getDescription() {
285 return Dictionary.get("FileAssociationDialog.Batch_File");
286 }
287 }
288
289 /** 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. */
290 private class BrowseButtonListener
291 implements ActionListener {
292 /** Open up a simple JFileChooser when the user clicks the button.
293 * @param event An <strong>ActionEvent</strong> containing information about the event.
294 */
295 public void actionPerformed(ActionEvent event) {
296 JFileChooser chooser = new JFileChooser(new File(Gatherer.getGLIUserDirectoryPath()));
297 GUIUtils.disableRename(chooser);
298 chooser.setDialogTitle(Dictionary.get("FileAssociationDialog.Browse_Title"));
299 chooser.setFileFilter(new BatchFileFilter());
300 chooser.setFileFilter(new CoreObjectModelFileFilter());
301 chooser.setFileFilter(new ExecutableFileFilter());
302 chooser.setAcceptAllFileFilterUsed(true);
303 if(chooser.showOpenDialog(Gatherer.g_man) == JFileChooser.APPROVE_OPTION) {
304 command_field.setText(chooser.getSelectedFile().getAbsolutePath());
305 }
306 }
307 }
308
309 private class CloseButtonListener
310 implements ActionListener {
311 public void actionPerformed(ActionEvent event) {
312 existing_associations_table.clearSelection();
313 add_button.setEnabled(false);
314 remove_button.setEnabled(false);
315 replace_button.setEnabled(false);
316 self.dispose();
317 }
318 }
319
320 /** Command filter shows only files ending in com. Based on ImageFilter.java which is a 1.4 example used by FileChooserDemo2.java. */
321 private class CoreObjectModelFileFilter
322 extends FileFilter {
323
324 /** Accept all .exe files
325 * @param file a File
326 * @return true is this file should be shown, false otherwise
327 */
328 public boolean accept(File file) {
329 return file.getName().toLowerCase().endsWith(".com");
330 }
331
332 /** The description of this filter
333 * @return a String
334 */
335 public String getDescription() {
336 return Dictionary.get("FileAssociationDialog.Command_File");
337 }
338 }
339
340 private class CommandOrExtensionFieldListener
341 implements DocumentListener {
342 /** Gives notification that an attribute or set of attributes changed. */
343 public void changedUpdate(DocumentEvent e) {
344 changed();
345 }
346 /** Gives notification that there was an insert into the document. */
347 public void insertUpdate(DocumentEvent e) {
348 changed();
349 }
350 /** Gives notification that a portion of the document has been removed. */
351 public void removeUpdate(DocumentEvent e) {
352 changed();
353 }
354
355 private void changed() {
356 ignore = true;
357 String extension_str = extension_field.getText();
358 String command_str = command_field.getText();
359 // Determine if there is currently an association selected
360 int selected_index = -1;
361 if((selected_index = existing_associations_table.getSelectionModel().getMinSelectionIndex()) != -1) {
362 String current_extension_str = file_association_manager.getExtension(selected_index);
363 String current_command_str = file_association_manager.getCommandString(current_extension_str);
364 // What buttons are enabled depends a lot on the file extension, taken to be the 'key'
365 if(extension_str.equals(current_extension_str)) {
366 // If the extensions are the same then remove is enabled
367 remove_button.setEnabled(true);
368 // But if the command is different, then enable replace
369 if(current_command_str.length() == 0) {
370 add_button.setEnabled(true);
371 replace_button.setEnabled(false);
372 }
373 else if(!command_str.equals(current_command_str)) {
374 add_button.setEnabled(false);
375 replace_button.setEnabled(true);
376 }
377 else {
378 add_button.setEnabled(false);
379 replace_button.setEnabled(false);
380 }
381 }
382 // We can add it, but we first clear the selection
383 else {
384 existing_associations_table.clearSelection();
385 add_button.setEnabled(true);
386 remove_button.setEnabled(false);
387 replace_button.setEnabled(false);
388 }
389 }
390 // If not, we must first test if the extension is in use
391 else {
392 int index = -1;
393 for(int i = 0; index == -1 && i < file_association_manager.size(); i++) {
394 String existing_extension_str = file_association_manager.getExtension(i);
395 if(existing_extension_str.equals(extension_str)) {
396 index = i;
397 }
398 }
399 if(index != -1) {
400 // Selection that index
401 existing_associations_table.setRowSelectionInterval(index, index);
402 // Set replace and remove enabled
403 add_button.setEnabled(false);
404 remove_button.setEnabled(true);
405 replace_button.setEnabled(true);
406 }
407 // Otherwise if there is some text in both extension and command, enable add only
408 else if(extension_str.length() > 0 && command_str.length() > 0) {
409 add_button.setEnabled(true);
410 remove_button.setEnabled(false);
411 replace_button.setEnabled(false);
412 }
413 // Otherwise disable everything
414 else {
415 add_button.setEnabled(false);
416 remove_button.setEnabled(false);
417 replace_button.setEnabled(false);
418 }
419 }
420 ignore = false;
421 }
422 }
423
424 /** Executable filter shows only files ending in exe. Based on ImageFilter.java which is a 1.4 example used by FileChooserDemo2.java. */
425 private class ExecutableFileFilter
426 extends FileFilter {
427
428 /** Accept all .exe files
429 * @param file a File
430 * @return true is this file should be shown, false otherwise
431 */
432 public boolean accept(File file) {
433 return file.getName().toLowerCase().endsWith(".exe");
434 }
435
436 /** The description of this filter
437 * @return a String
438 */
439 public String getDescription() {
440 return Dictionary.get("FileAssociationDialog.Executable_File");
441 }
442 }
443
444 private class ExistingAssociationsTableListener
445 implements ListSelectionListener {
446
447 public void valueChanged(ListSelectionEvent event) {
448 if(!event.getValueIsAdjusting() && !ignore) {
449 int selected_index = -1;
450 if((selected_index = existing_associations_table.getSelectionModel().getMinSelectionIndex()) != -1) {
451 // Propagate the details of the selection down into the fields
452 String extension_str = file_association_manager.getExtension(selected_index);
453 extension_field.setText(extension_str);
454 command_field.setText(file_association_manager.getCommandString(extension_str));
455 extension_str = null;
456 remove_button.setEnabled(true);
457 }
458 else {
459 // Clear the fields
460 extension_field.setText("");
461 command_field.setText("");
462 remove_button.setEnabled(false);
463 }
464 add_button.setEnabled(false);
465 replace_button.setEnabled(false);
466 }
467 }
468 }
469
470 private class RemoveButtonListener
471 implements ActionListener {
472 public void actionPerformed(ActionEvent event) {
473 file_association_manager.setCommand(extension_field.getText(), null);
474 // And update buttons
475 add_button.setEnabled(true);
476 remove_button.setEnabled(false);
477 }
478 }
479
480 private class ReplaceButtonListener
481 implements ActionListener {
482 public void actionPerformed(ActionEvent event) {
483 file_association_manager.setCommand(extension_field.getText(), command_field.getText());
484 // And update buttons
485 replace_button.setEnabled(false);
486 }
487 }
488}
489
490
491
492
493
494
Note: See TracBrowser for help on using the repository browser.