source: gli/branches/rtl-gli/src/org/greenstone/gatherer/gui/DownloadPane.java@ 18297

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

interface updated to display right to left for rtl languages. This code is thanks to Amin Hejazi. It seems to be only partially complete. Amin was working with Greenstone 3 so might have missed some panels

  • Property svn:keywords set to Author Date Id Revision
File size: 22.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.*;
42import java.net.*;
43import java.util.*;
44import javax.swing.*;
45import javax.swing.border.*;
46import javax.swing.event.*;
47import javax.swing.tree.*;
48import org.greenstone.gatherer.Configuration;
49import org.greenstone.gatherer.DebugStream;
50import org.greenstone.gatherer.Dictionary;
51import org.greenstone.gatherer.Gatherer;
52import org.greenstone.gatherer.file.WorkspaceTree;
53import org.greenstone.gatherer.greenstone.LocalGreenstone;
54import org.greenstone.gatherer.util.StaticStrings;
55import org.greenstone.gatherer.util.Utility;
56import org.greenstone.gatherer.download.Download;
57import org.greenstone.gatherer.download.DownloadScrollPane;
58import org.greenstone.gatherer.download.ServerInfoDialog;
59import org.greenstone.gatherer.util.XMLTools;
60import org.greenstone.gatherer.cdm.*;
61import org.greenstone.gatherer.gui.*;
62import org.w3c.dom.*;
63import org.xml.sax.*;
64import org.greenstone.gatherer.GAuthenticator;
65
66/**
67 * @author John Thompson, Greenstone Digital Library, University of Waikato
68 * @version 2.1
69 */
70public class DownloadPane
71 extends JPanel {
72
73 static final private Dimension LABEL_SIZE = new Dimension(225, 25);
74 static final private Dimension TREE_SIZE = new Dimension(150, 500);
75 static final private String CONTENTS[] = { "DOWNLOAD.MODE.WebDownload", "DOWNLOAD.MODE.MediaWikiDownload", "DOWNLOAD.MODE.OAIDownload", "DOWNLOAD.MODE.ZDownload" , "DOWNLOAD.MODE.SRWDownload"};
76
77 private boolean download_button_enabled = false;
78 private boolean ready = false;
79
80 private JPanel options_pane;
81 // TODO should use Vector to store all loaded downloads!!
82
83 private DesignTree tree;
84 private HashMap download_map;
85 private ServerInfoDialog server_info;
86 private JScrollPane list_scroll;
87 private DownloadScrollPane getter;
88 private String mode = null;
89 private TreePath previous_path;
90 private String proxy_url = "";
91
92 /** Main System code */
93 public DownloadPane() {
94 super();
95 JScrollPane scrol_tmp;
96 this.setComponentOrientation(Dictionary.getOrientation());
97 // TODO: Download the WDownload and the download panel fixed!!
98 getter = new DownloadScrollPane();
99 getter.start();
100 list_scroll = getter.getDownloadJobList();
101 list_scroll.setComponentOrientation(Dictionary.getOrientation());
102 // TODO should use Vector to store all loaded downloads!!
103 String lang = Configuration.getLanguage();
104 download_map = new HashMap();
105 download_map.put("Web", loadDownload("WebDownload",lang));
106 download_map.put("MediaWiki", loadDownload("MediaWikiDownload",lang));
107 download_map.put("OAI", loadDownload("OAIDownload",lang));
108 download_map.put("Z3950", loadDownload("Z3950Download",lang));
109 download_map.put("SRW", loadDownload("SRWDownload",lang));
110
111 // Creation
112 tree = new DesignTree();
113 tree.setComponentOrientation(Dictionary.getOrientation());
114 options_pane = new JPanel();
115 options_pane.setComponentOrientation(Dictionary.getOrientation());
116
117 JButton clear_cache_button = new GLIButton(Dictionary.get("Mirroring.ClearCache"), Dictionary.get("Mirroring.ClearCache_Tooltip"));
118 clear_cache_button.setEnabled(true);
119 clear_cache_button.setMnemonic(KeyEvent.VK_C);
120
121 JButton download_button = new GLIButton(Dictionary.get("Mirroring.Download"), Dictionary.get("Mirroring.Download_Tooltip"));
122 download_button.setEnabled(true);
123 download_button.setMnemonic(KeyEvent.VK_D);
124
125 JButton information_button = new GLIButton(Dictionary.get("Download.ServerInformation"), Dictionary.get("Download.ServerInformation_Tooltip"));
126 information_button.setEnabled(true);
127 information_button.setMnemonic(KeyEvent.VK_S);
128
129
130 JButton preferences_button = new GLIButton(Dictionary.get("Mirroring.Preferences"), Dictionary.get("Mirroring.Preferences_Tooltip"));
131 preferences_button.setEnabled(true);
132 preferences_button.setMnemonic(KeyEvent.VK_P);
133
134 // Connect
135 clear_cache_button.addActionListener(new ClearCacheListener());
136 download_button.addActionListener(new DownloadButtonListener());
137 preferences_button.addActionListener(new PreferencesButtonActionListener());
138 information_button.addActionListener(new InformationButtonActionListener());
139 tree.addTreeSelectionListener(new TreeListener());
140
141 // Add to Panel
142 JPanel button_pane = new JPanel();
143 button_pane.setComponentOrientation(Dictionary.getOrientation());
144 button_pane.setLayout(new FlowLayout(FlowLayout.CENTER,20,5));
145 button_pane.setBorder(BorderFactory.createEtchedBorder());
146 button_pane.add(clear_cache_button);
147 button_pane.add(download_button);
148 button_pane.add(information_button);
149 button_pane.add(preferences_button);
150
151 JPanel tree_pane = new JPanel();
152 tree_pane.setComponentOrientation(Dictionary.getOrientation());
153 tree_pane.setLayout(new BorderLayout());
154 scrol_tmp = new JScrollPane(tree);
155 scrol_tmp.setComponentOrientation(Dictionary.getOrientation());
156 tree_pane.add(scrol_tmp, BorderLayout.CENTER);
157 tree_pane.setPreferredSize(TREE_SIZE);
158
159
160 Color colour_two = Configuration.getColor("coloring.collection_tree_background", false);
161 options_pane.setBackground(colour_two);
162 options_pane.setBorder(BorderFactory.createEtchedBorder());
163
164
165 JScrollPane options_scroll_pane = new JScrollPane(options_pane);
166 options_scroll_pane.setComponentOrientation(Dictionary.getOrientation());
167 JSplitPane mode_pane = new JSplitPane();
168 mode_pane.setComponentOrientation(Dictionary.getOrientation());
169 mode_pane.setBorder(BorderFactory.createEmptyBorder(0,0,0,0));
170 if (Dictionary.getOrientation().isLeftToRight()){
171 mode_pane.add(tree_pane,JSplitPane.LEFT);
172 mode_pane.add(options_scroll_pane,JSplitPane.RIGHT);
173 mode_pane.setDividerLocation(TREE_SIZE.width);
174 }else{
175 mode_pane.add(tree_pane,JSplitPane.RIGHT);
176 mode_pane.add(options_scroll_pane,JSplitPane.LEFT);
177 mode_pane.setDividerLocation(1);
178 }
179
180
181 JPanel edit_pane = new JPanel();
182 edit_pane.setComponentOrientation(Dictionary.getOrientation());
183 edit_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(2,0,0,0), BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("Download Setting"), BorderFactory.createEmptyBorder(2,2,2,2))));
184 edit_pane.setLayout(new BorderLayout());
185 edit_pane.add(mode_pane,BorderLayout.CENTER);
186 edit_pane.add(button_pane,BorderLayout.PAGE_END);
187
188 // Add to "this"
189 setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
190 setLayout(new GridLayout(2,1));
191 add(edit_pane);
192 add(list_scroll);
193
194 mode = "Web";
195 generateOptions(options_pane,(Download)download_map.get(mode));
196 previous_path = tree.getSelectionPath();
197 }
198
199 /** System Utilities */
200 public void modeChanged(int gli_mode) {
201 // do nothing at this stage - should we be renewing download options??
202 }
203
204 private void addHeader(String name, Color color, JPanel target_pane) {
205 JPanel header = new JPanel();
206 header.setComponentOrientation(Dictionary.getOrientation());
207 header.setBackground(color);
208 JPanel inner_pane = new JPanel();
209 inner_pane.setComponentOrientation(Dictionary.getOrientation());
210 inner_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(5,5,5,5), BorderFactory.createRaisedBevelBorder()));
211 inner_pane.setBackground(color);
212 JLabel header_label = new JLabel("<html><strong>" + name + "</strong></html>");
213 header_label.setComponentOrientation(Dictionary.getOrientation());
214 header_label.setBackground(Configuration.getColor("coloring.collection_heading_background", false));
215 header_label.setHorizontalAlignment(JLabel.CENTER);
216 header_label.setOpaque(true);
217
218 // Layout
219 inner_pane.setLayout(new BorderLayout());
220 inner_pane.add(header_label, BorderLayout.CENTER);
221
222 header.setLayout(new BorderLayout());
223 header.add(inner_pane, BorderLayout.CENTER);
224 target_pane.add(header);
225 }
226
227 /** Supporting Functions */
228 private Download loadDownload(String download_name, String lang) {
229 Document document = null;
230 InputStream input_stream = null;
231
232 try {
233 if (Gatherer.isGsdlRemote) {
234 StringBuffer launch_str = new StringBuffer();
235 launch_str.append(Gatherer.cgiBase);
236 launch_str.append("launch");
237 launch_str.append("?cmd=downloadinfo.pl&xml=&language=");
238 launch_str.append(lang);
239 launch_str.append("&plug=");
240 launch_str.append(download_name);
241
242 String launch = launch_str.toString();
243 System.err.println("*** launch = " + launch);
244
245 URL launch_url = new URL(launch);
246 URLConnection launch_connection = launch_url.openConnection();
247 input_stream = launch_connection.getInputStream();
248 }
249 else {
250 ArrayList args_list = new ArrayList();
251 String args[] = null;
252 if(Utility.isWindows()) {
253 if(Configuration.perl_path != null) {
254 args_list.add(Configuration.perl_path);
255 }
256 else {
257 args_list.add("Perl.exe");
258 }
259 }
260 args_list.add(LocalGreenstone.getBinScriptDirectoryPath()+"downloadinfo.pl");
261 args_list.add("-xml");
262 args_list.add("-language");
263 args_list.add(lang);
264 args_list.add(download_name);
265
266 // Create the process.
267 args = (String []) args_list.toArray(new String[0]);
268 Runtime runtime = Runtime.getRuntime();
269 DebugStream.println("Getting Download Info: "+args_list);
270 Process process = runtime.exec(args);
271
272 input_stream = process.getErrorStream();
273 }
274
275 document = XMLTools.parseXML(input_stream);
276 }
277 catch (Exception error) {
278 System.err.println("Failed when trying to parse: " + download_name);
279 error.printStackTrace();
280 }
281
282 if(document != null) {
283 return parseXML(document.getDocumentElement());
284 }
285
286 return null;
287 }
288
289 private Download parseXML(Node root) {
290 Download download = new Download();
291 String node_name = null;
292 for (Node node = root.getFirstChild(); node != null; node = node.getNextSibling()) {
293 node_name = node.getNodeName();
294 if(node_name.equalsIgnoreCase("Name")) {
295 String name = XMLTools.getValue(node);
296 download.setName(name);
297 }
298 else if (node_name.equalsIgnoreCase("Desc")) {
299 download.setDescription(XMLTools.getValue(node));
300 }
301 else if (node_name.equalsIgnoreCase("Abstract")) {
302 download.setIsAbstract(XMLTools.getValue(node).equalsIgnoreCase(StaticStrings.YES_STR));
303 }
304 else if(node_name.equalsIgnoreCase("Arguments")) {
305 for(Node arg = node.getFirstChild(); arg != null; arg = arg.getNextSibling()) {
306 node_name = arg.getNodeName();
307 if(node_name.equalsIgnoreCase("Option")) {
308 Argument argument = new Argument((Element)arg);
309 argument.parseXML((Element)arg);
310 argument.setValue(argument.getDefaultValue());
311 download.addArgument(argument);
312 }
313
314 }
315 }
316 else if(node_name.equalsIgnoreCase("DownloadInfo")) {
317 Download super_download = parseXML(node);
318 download.setSuper(super_download);
319 }
320 }
321
322 if(download.getName() != null) {
323 return download;
324 }
325 return null;
326 }
327
328 /** Update the previous setup */
329 private boolean updateArguments(boolean checkRequired)
330 {
331 boolean cont = true;
332 for(int i = 0; i < options_pane.getComponentCount(); i++) {
333
334 Component component = options_pane.getComponent(i);
335 if(component instanceof ArgumentControl) {
336 cont = cont && ((ArgumentControl)component).updateArgument(checkRequired);
337 }
338 }
339
340 if(cont){return true; }
341
342 return false;
343 }
344
345 /** Generate Controls for Options */
346 /* at some stage we should think about which options should be shown for
347 * different modes. Currently, always show all options (unless hidden)*/
348 private void generateOptions(JPanel options_pane, ArgumentContainer data) {
349 options_pane.removeAll();
350 /** Create the current option panel */
351
352 ArrayList arguments = data.getArguments(true, false);
353 int mode = Configuration.getMode();
354 ArrayList added_arguments = new ArrayList();
355
356 for(int i = 0; i < arguments.size(); i++) {
357 Argument argument = (Argument) arguments.get(i);
358
359 if (argument.isHiddenGLI()) continue;
360 ArgumentControl argument_control = new ArgumentControl(argument,false,null);
361 added_arguments.add(argument_control);
362 }
363
364
365 options_pane.setLayout(new GridLayout(added_arguments.size(),1));
366 for(int i = 0; i < added_arguments.size(); i++) {
367 options_pane.add((ArgumentControl)added_arguments.get(i));
368
369 }
370 }
371
372 /** Behaviour Functions */
373 public void afterDisplay() {
374 ready = true;
375 }
376
377
378 public void gainFocus() {
379 if(!ready) {
380 return;
381 }
382
383 // It is also a good time to determine if the download should be enabled - ie if its allowed to be enabled and a valid URL is present in the field.
384 download_button_enabled = true;
385 //download_button.setEnabled(download_button_enabled);
386 }
387
388
389
390 public void refresh(int refresh_reason, boolean ready)
391 {
392 }
393
394 /** Private classes */
395 /** This tree provides a 'table of contents' for the various components of the design process (collection configuration in more technical terms). */
396 private class DesignTree extends JTree {
397
398 private DesignNode root = null;
399 /** Constructor. Automatically generates all of the nodes, in the order of CONTENTS. */
400 public DesignTree() {
401 super();
402 resetModel(Configuration.getMode());
403 expandRow(0);
404 setRootVisible(false);
405 setSelectionRow(0);
406 }
407
408 /** Reset the model used by the design page contents tree. This is necessary to hide the partitions entry when in lower detail modes
409 * @param mode the current detail mode as an int
410 */
411 public void resetModel(int mode) {
412 root = new DesignNode("DOWNLOAD.MODE.Root");
413 // Now add the design categories.
414 for(int i = 0; i < CONTENTS.length; i++) {
415 root.add(new DesignNode(CONTENTS[i]));
416 }
417 this.setModel(new DefaultTreeModel(root));
418 updateUI();
419 }
420 /** Set the current view to the one specified.
421 * @param type the name of the desired view as a String
422 */
423 public void setSelectedView(String type) {
424 type = Dictionary.get(type);
425 for(int i = 0; i < root.getChildCount(); i++) {
426 DesignNode child = (DesignNode) root.getChildAt(i);
427 if(child.toString().equals(type)) {
428 TreePath path = new TreePath(child.getPath());
429 setSelectionPath(path);
430 }
431 }
432 }
433 }
434
435 /** A tree node that retains a reference to one of the possible design sub-views relating to the different sub-managers. */
436 private class DesignNode extends DefaultMutableTreeNode {
437 /** Constructor.
438 * @param object The <strong>Object</strong> assigned to this node.
439 */
440 public DesignNode(String object) {
441 super(object);
442 }
443 /** Retrieve a textual representation of the object.
444 * @return a String
445 */
446 public String toString() {
447 // return Dictionary.get("CDM.GUI." + (String)getUserObject());
448 return Dictionary.get((String) getUserObject());
449 }
450 }
451
452 /** Listens for selection changes in the 'contents' tree, and switches to the appropriate view. */
453 private class TreeListener
454 implements TreeSelectionListener {
455 /** Called whenever the selection changes, we must update the view so it matches the node selected.
456 * @param event A <strong>TreeSelectionEvent</strong> containing more information about the tree selection.
457 * @see org.greenstone.gatherer.cdm.ClassifierManager
458 * @see org.greenstone.gatherer.cdm.CollectionDesignManager
459 * @see org.greenstone.gatherer.cdm.CollectionMetaManager
460 * @see org.greenstone.gatherer.cdm.FormatManager
461 * @see org.greenstone.gatherer.cdm.LanguageManager
462 * @see org.greenstone.gatherer.cdm.MetadataSetView
463 * @see org.greenstone.gatherer.cdm.SubcollectionManager
464 * @see org.greenstone.gatherer.cdm.TranslationView
465 * @see org.greenstone.gatherer.cdm.PlugInManager
466 */
467 public void valueChanged(TreeSelectionEvent event) {
468 if(!tree.isSelectionEmpty()) {
469 TreePath path = tree.getSelectionPath();
470
471 DesignNode node = (DesignNode)path.getLastPathComponent();
472 String type = (String)node.getUserObject();
473 Gatherer.g_man.wait(true);
474 if(type == CONTENTS[0]) {
475 mode = "Web";
476 generateOptions(options_pane,(Download)download_map.get(mode));
477 }
478 else if(type == CONTENTS[1]) {
479 mode = "MediaWiki";
480 generateOptions(options_pane,(Download)download_map.get(mode));
481 }
482 else if(type == CONTENTS[2]) {
483 mode = "OAI";
484 generateOptions(options_pane,(Download)download_map.get(mode));
485 }
486 else if(type == CONTENTS[3]) {
487 mode = "Z3950";
488 generateOptions(options_pane,(Download)download_map.get(mode));
489 }
490 else if(type == CONTENTS[4]) {
491 mode = "SRW";
492 generateOptions(options_pane,(Download)download_map.get(mode));
493 }
494 tree.setSelectionPath(path);
495 previous_path = path;
496 repaint();
497
498 Gatherer.g_man.wait(false);
499 }
500 }
501 }
502
503 private class ClearCacheListener
504 implements ActionListener {
505 public void actionPerformed(ActionEvent event) {
506 // Retrieve the cache folder and delete it.
507 Utility.delete(Utility.getCacheDir());
508 // ...and refresh the node in the workspace tree to show it's all gone
509 Gatherer.g_man.refreshWorkspaceTree(WorkspaceTree.DOWNLOADED_FILES_CHANGED);
510 }
511 }
512
513 private class DownloadButtonListener
514 implements ActionListener {
515 public void actionPerformed(ActionEvent event) {
516
517 if(checkURL(true) && checkProxy() == true) {
518
519 getter.newDownloadJob((Download)download_map.get(mode) ,mode,proxy_url);
520 }
521 }
522 }
523
524
525 private boolean checkURL(boolean checkRequired){
526
527 if (!updateArguments(checkRequired)){
528 return false;
529 }
530
531 Download current_download = (Download)download_map.get(mode);
532 Argument arg_url = current_download.getArgument("url");
533
534 if (arg_url == null) return true;
535
536 String url_str = arg_url.getValue();
537 URL url = null;
538 try {
539 url = new URL(url_str);
540 }
541 catch(MalformedURLException error) {
542 JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("Mirroring.Invalid_URL"), Dictionary.get("Mirroring.Invalid_URL_Title"), JOptionPane.ERROR_MESSAGE);
543 return false;
544 }
545
546 return true;
547 }
548
549
550 private boolean checkProxy(){
551
552 proxy_url = null;
553
554 Download current_download = (Download)download_map.get(mode);
555
556 Argument arg = current_download.getArgument("proxy_on");
557
558 if (arg == null) return true;
559
560 // Determine if we have to use a proxy.
561 if(Configuration.get("general.use_proxy", true)) {
562
563 String proxy_host = Configuration.getString("general.proxy_host", true);
564 String proxy_port = Configuration.getString("general.proxy_port", true);
565 // Find out whether the user has already authenticated themselves
566 String user_pass = "";
567 String address = proxy_host + ":" + proxy_port;
568
569 int count = 0;
570 while(count < 3 && (user_pass = (String) GAuthenticator.authentications.get(address)) == null) {
571 Authenticator.requestPasswordAuthentication(proxy_host, null, Integer.parseInt(proxy_port), "http://", Dictionary.get("WGet.Prompt"), "HTTP");
572 count++;
573 }
574
575 if(count >= 3) {
576 return false;
577 }
578
579 if(user_pass.indexOf("@") != -1) {
580
581 // Write the use proxy command - we don't do this anymore, instead we set environment variables - hopefully these can't be spied on like the follwoing can (using ps) - actually the environment stuff didn't work for windows, so lets go back to this
582 if (Utility.isWindows()) {
583
584 arg.setValue("true");
585 arg.setAssigned(true);
586
587 arg = current_download.getArgument("proxy_host");
588 arg.setValue(proxy_host);
589 arg.setAssigned(true);
590
591 arg = current_download.getArgument("proxy_port");
592 arg.setValue(proxy_port);
593 arg.setAssigned(true);
594
595 arg = current_download.getArgument("user_name");
596 arg.setValue(user_pass.substring(0, user_pass.indexOf("@")));
597 arg.setAssigned(true);
598
599 arg = current_download.getArgument("user_password");
600 arg.setValue(user_pass.substring(user_pass.indexOf("@") + 1));
601 arg.setAssigned(true);
602 }
603 else{
604 String user_name = user_pass.substring(0, user_pass.indexOf("@"));
605 String user_pwd = user_pass.substring(user_pass.indexOf("@") + 1);
606 proxy_url = user_name+":"+user_pwd+"@"+proxy_host+":"+proxy_port+"/";
607
608 }
609
610 return true;
611 }
612 else{
613 return false;
614 }
615
616 }
617
618 return true;
619 }
620
621 /*
622 private class PreferencesButtonActionListener
623 implements ActionListener {
624 public void actionPerformed(ActionEvent event) {
625 new Preferences(Preferences.CONNECTION_PREFS);
626 }
627 }*/
628
629 private class InformationButtonActionListener
630 implements ActionListener {
631 public void actionPerformed(ActionEvent event) {
632 //turn off the check for find argument
633 Download current_download = (Download)download_map.get(mode);
634
635 if (!checkProxy() || !checkURL(false) )return;
636
637
638 if(server_info != null) {
639 server_info.dispose();
640 }
641
642
643 Argument arg_url = current_download.getArgument("url");
644 String str_url = "";
645
646 if( arg_url!= null && arg_url.isAssigned()) {
647 str_url = arg_url.getValue();
648 }
649
650
651 server_info = new ServerInfoDialog(str_url ,proxy_url, mode,(Download)download_map.get(mode));
652
653 }
654 }
655
656 private class PreferencesButtonActionListener
657 implements ActionListener {
658 public void actionPerformed(ActionEvent event) {
659 new Preferences(Preferences.CONNECTION_PREFS);
660 }
661 }
662}
Note: See TracBrowser for help on using the repository browser.