source: trunk/gli/src/org/greenstone/gatherer/cdm/PluginManager.java@ 12293

Last change on this file since 12293 was 12293, checked in by kjdon, 18 years ago

getExploderPlugin changed to getExploderPlugins, and returns an ArrayList of possible plugins

  • Property svn:keywords set to Author Date Id Revision
File size: 47.6 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 * Author: John Thompson, Greenstone Digital Library, University of Waikato
9 *
10 * Copyright (C) 1999 New Zealand Digital Library Project
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 *########################################################################
26 */
27package org.greenstone.gatherer.cdm;
28
29import java.awt.*;
30import java.awt.event.*;
31import java.io.*;
32import java.net.*;
33import java.util.*;
34import javax.swing.*;
35import javax.swing.event.*;
36import javax.swing.plaf.*;
37import javax.swing.plaf.basic.*;
38import org.apache.xerces.parsers.*;
39import org.greenstone.gatherer.Configuration;
40import org.greenstone.gatherer.DebugStream;
41import org.greenstone.gatherer.Dictionary;
42import org.greenstone.gatherer.Gatherer;
43import org.greenstone.gatherer.LocalGreenstone;
44import org.greenstone.gatherer.collection.CollectionContentsChangedListener;
45import org.greenstone.gatherer.gui.DesignPaneHeader;
46import org.greenstone.gatherer.gui.GComboBox;
47import org.greenstone.gatherer.gui.GLIButton;
48import org.greenstone.gatherer.gui.ModalDialog;
49import org.greenstone.gatherer.gui.WarningDialog;
50import org.greenstone.gatherer.remote.RemoteGreenstoneServer;
51import org.greenstone.gatherer.util.JarTools;
52import org.greenstone.gatherer.util.StaticStrings;
53import org.greenstone.gatherer.util.Utility;
54import org.greenstone.gatherer.util.XMLTools;
55import org.w3c.dom.*;
56import org.xml.sax.*;
57
58
59/** This class is for maintaining a list of known plug-ins, and importing new plugins using the parser. */
60public class PluginManager
61 extends DOMProxyListModel
62 implements CollectionContentsChangedListener
63{
64 /** The library 'reserve' of base plugins. */
65 private ArrayList library = null;
66 /** When asking how many rows are in the model, and if this variables value is true, then this modifier alters the number returned. This funtionality is used to hide the last three rows of the list in low detail modes. */
67 private boolean modify_row_count = false;
68 /** The controls for editing the contents of this manager. */
69 private Control controls = null;
70 private DOMProxyListModel model;
71 private JPanel separator;
72 private Plugin separator_plugin;
73 /** Constructor.
74 */
75 public PluginManager() {
76 super(CollectionDesignManager.collect_config.getDocumentElement(), CollectionConfiguration.PLUGIN_ELEMENT, new Plugin());
77 DebugStream.println("PluginManager: " + super.getSize() + " plugins parsed.");
78 model = this;
79 // Reload/Create the library
80 loadPlugins(); // adds all the plugins to the library
81 savePlugins();
82 // Create the separator, cause we can reuse it.
83 separator = getSeparator();
84
85 // Listen for CollectionContentsChanged events, so we can give plugin hints when new files are added
86 Gatherer.c_man.addCollectionContentsChangedListener(this);
87 }
88
89 /** Method to add a new plugin to the library
90 * @param plugin the new base Plugin
91 */
92 private void addPlugin(Plugin plugin) {
93 if(!library.contains(plugin)) {
94 library.add(plugin);
95 }
96 }
97
98 /** Method to assign a plugin
99 * @param plugin the Plugin to assign
100 */
101 private void assignPlugin(Plugin plugin) {
102 if(plugin.getName().equals(StaticStrings.RECPLUG_STR) || plugin.getName().equals(StaticStrings.ARCPLUG_STR)) {
103 addAfter(plugin, separator_plugin); // Adds after separator
104 } else {
105 addBefore(plugin, separator_plugin);
106 }
107 Gatherer.c_man.configurationChanged();
108 }
109
110 public static boolean clearPluginCache() {
111
112 DebugStream.println("deleting plugins.dat");
113 File plugin_file = new File(Gatherer.getGLIUserDirectoryPath() + "plugins.dat");
114 if (plugin_file.exists()) {
115 return Utility.delete(plugin_file);
116 }
117 return true;
118 }
119
120
121 /** Destructor. */
122 public void destroy()
123 {
124 Gatherer.c_man.removeCollectionContentsChangedListener(this);
125
126 if (controls != null) {
127 controls.destroy();
128 controls = null;
129 }
130
131 library.clear();
132 library = null;
133 }
134
135
136 /** This function listens for new files being added to the collection and hints about suitable plugins. */
137 public void fileAddedToCollection(File file)
138 {
139 // First check the plugins already assigned in the collection
140 for (int i = 0; i < super.getSize(); i++) {
141 Plugin assigned_plugin = (Plugin) getElementAt(i);
142 if (assigned_plugin.isSeparator() == false && (assigned_plugin.doesProcessFile(file) == true || assigned_plugin.doesBlockFile(file) == true)) {
143 // This file will be processed by an assigned plugin, so no suggestion is necessary
144 DebugStream.println("Processed by assigned plugin: " + assigned_plugin);
145 return;
146 }
147 }
148
149 // Next try the plugins NOT already assigned in the collection
150 ArrayList suitable_plugins = new ArrayList();
151 Object[] unassigned_plugins = getAvailable();
152 for (int i = 0; i < unassigned_plugins.length; i++) {
153 Plugin unassigned_plugin = (Plugin) unassigned_plugins[i];
154 if (unassigned_plugin.doesProcessFile(file) == true) {
155 DebugStream.println("Processed by unassigned plugin: " + unassigned_plugin);
156 suitable_plugins.add(unassigned_plugin);
157 }
158 }
159
160 // If there appear to be no suitable plugins, warn the user about this and be done
161 if (suitable_plugins.size() == 0) {
162 String[] args = new String[1];
163 args[0] = file.getName();
164 WarningDialog warning_dialog = new WarningDialog("warning.NoPluginExpectedToProcessFile", "NoPluginExpectedToProcessFile.Title", Dictionary.get("NoPluginExpectedToProcessFile.Message", args), null, false);
165 warning_dialog.display();
166 warning_dialog.dispose();
167 return;
168 }
169
170 // Generate a dialog
171 new PluginSuggestionPrompt(file.getName(), suitable_plugins);
172 }
173
174
175 public boolean isFileExplodable(File file)
176 {
177
178 for (int i = 0; i < library.size(); i++) {
179 Plugin plugin = (Plugin) library.get(i);
180 if (plugin.doesExplodeMetadataDatabases() == true && plugin.doesProcessFile(file) == true) {
181 return true;
182 }
183 }
184
185 return false;
186 }
187
188 public ArrayList getExploderPlugins(File file)
189 {
190 ArrayList exp_plugins = new ArrayList();
191 for (int i = 0; i < library.size(); i++) {
192 Plugin plugin = (Plugin) library.get(i);
193 if (plugin.doesProcessFile(file) == true && plugin.doesExplodeMetadataDatabases() == true) {
194 exp_plugins.add(plugin);
195 }
196 }
197 return exp_plugins;
198 }
199
200 /** Method to retrieve the control for this manager.
201 * @return the Control
202 */
203 public Control getControls() {
204 if(controls == null) {
205 // Build controls
206 controls = new PluginControl();
207 }
208 return controls;
209 }
210
211 /** Retrieve the base plugin of the given name, or null if no such plugin.
212 * @param name the name of the base plugin to retrieve as a String
213 * @return the Plugin requested or null if no such plugin
214 */
215 public Plugin getBasePlugin(String name) {
216 int library_size = library.size();
217 for(int i = 0; i < library_size; i++) {
218 Plugin plugin = (Plugin) library.get(i);
219 if(plugin.getName().equals(name)) {
220 return plugin;
221 }
222 }
223 // No success.
224 return null;
225 }
226
227 /** Overrides getSize in DOMProxyListModel to take into account the row count modifier used to hide the last three rows in lower detail modes
228 * @return an int indicating the number of rows in the model, or more correctly the desired number of rows to display
229 */
230 public int getSize() {
231 int result = super.getSize();
232 if(modify_row_count) {
233 result = result-3;
234 }
235 return result;
236 }
237
238 /** Called when the detail mode has changed which in turn may cause several design elements to be available/hidden
239 * @param mode the new mode as an int
240 */
241 public void modeChanged(int mode) {
242 if(controls != null) {
243 ((PluginControl)controls).modeChanged(mode);
244 }
245 }
246
247 /** Method to move a plugin in the list order.
248 * @param plugin the Plugin you want to move.
249 * @param direction true to move the plugin up, false to move it down.
250 * @param all true to move to move all the way, false for a single step.
251 */
252 // why are all the error notices there when the buttons are disabled is you cant move???
253 private void movePlugin(Plugin plugin, boolean direction, boolean all) {
254 // Can't ever move RecPlug or ArcPlug
255 if(super.getSize() < 4) {
256 //DebugStream.println("Not enough plugins to allow moving.");
257 return;
258 }
259 if(plugin.getName().equals(StaticStrings.ARCPLUG_STR) || plugin.getName().equals(StaticStrings.RECPLUG_STR)) {
260 JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CDM.Move.Fixed"), Dictionary.get("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE);
261 return;
262 }
263 if(all) {
264 // Move to top
265 if(direction) {
266 // Remove the moving plugin
267 remove(plugin);
268 // Retrieve the first plugin
269 Plugin first_plugin = (Plugin) getElementAt(0);
270 // Add the moving plugin before the first plugin
271 addBefore(plugin, first_plugin);
272 first_plugin = null;
273 Gatherer.c_man.configurationChanged();
274 }
275 else {
276 // Remove the moving plugin
277 remove(plugin);
278 // Add the moving plugin before the separator
279 addBefore(plugin, separator_plugin);
280 Gatherer.c_man.configurationChanged();
281 }
282 }
283 else {
284 // Try to move the plugin one step in the desired direction.
285 int index = indexOf(plugin);
286 ///ystem.err.println("Index of " + plugin + " = " + index);
287 if(direction) {
288 index--;
289 if(index < 0) {
290 String args[] = new String[2];
291 args[0] = Dictionary.get("CDM.PlugInManager.PlugIn_Str");
292 args[1] = plugin.getName();
293 JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CDM.Move.At_Top", args), Dictionary.get("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE);
294 return;
295 }
296 remove(plugin);
297 add(index, plugin);
298 Gatherer.c_man.configurationChanged();
299 }
300 else {
301 index++;
302 Plugin next_plugin = (Plugin) getElementAt(index);
303 if(next_plugin.isSeparator()) {
304 String args[] = new String[1];
305 args[0] = plugin.getName();
306 JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CDM.Move.Cannot", args), Dictionary.get("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE);
307 // Still not going to move RecPlug or ArcPlug.
308 return;
309 }
310 remove(plugin);
311 add(index, plugin);
312 Gatherer.c_man.configurationChanged();
313 }
314 }
315 }
316
317 /** We attempt to place the separator between the unfixed and the fixed plugins. Since we only know of two fixed plugins, we search for either of them, and place the separator before them.
318 */
319 public void placeSeparator() {
320 ///ystem.err.println("Placing separator.");
321 int separator_index = super.getSize();
322 if(separator_index > 0) {
323 boolean found_fixed = false;
324 int index = separator_index - 1;
325 while(index > 0) {
326 Plugin plugin = (Plugin) getElementAt(index);
327 String name = plugin.getName();
328 if(name.equals(StaticStrings.RECPLUG_STR) || name.equals(StaticStrings.ARCPLUG_STR)) {
329 found_fixed = true;
330 index--;
331 }
332 else {
333 if(found_fixed) {
334 separator_index = index + 1;
335 index = -1;
336 }
337 else {
338 index--;
339 }
340 }
341 name = null;
342 plugin = null;
343 }
344 }
345 Element element = CollectionDesignManager.collect_config.document.createElement(CollectionConfiguration.PLUGIN_ELEMENT);
346 element.setAttribute(CollectionConfiguration.TYPE_ATTRIBUTE, CollectionConfiguration.SEPARATOR_ATTRIBUTE);
347 element.setAttribute(CollectionConfiguration.SEPARATOR_ATTRIBUTE, CollectionConfiguration.TRUE_STR);
348 separator_plugin = new Plugin(element, null);
349 ///atherer.println("Adding plugin separator at: " + separator_index);
350 add(separator_index, separator_plugin);
351 }
352
353 /** This method removes an assigned plugin. I was tempted to call it unassign, but remove is more consistant. Note that there is no way to remove a plugin from the library.
354 * @param plugin The <strong>Plugin</strong> to remove.
355 */
356 private void removePlugin(Plugin plugin) {
357 remove(plugin);
358 Gatherer.c_man.configurationChanged();
359 }
360
361 /** Method to cache the current contents of library (known plugins) to file.
362 */
363 private void savePlugins() {
364 try {
365 File plugins_dat_file = new File(Gatherer.getGLIUserDirectoryPath() + "plugins.dat");
366 FileOutputStream file = new FileOutputStream(plugins_dat_file);
367 ObjectOutputStream out = new ObjectOutputStream(file);
368 out.writeObject(library);
369 out.close();
370 }
371 catch (Exception error) {
372 DebugStream.printStackTrace(error);
373 }
374 }
375
376 /** Inform the model to hide/show the last three lines on the list.
377 * @param modify_row_count true to hide the last three lines, false otherwise
378 */
379 private void setHideLines(boolean modify_row_count) {
380 this.modify_row_count = modify_row_count;
381 int original_size = super.getSize();
382 if(modify_row_count) {
383 fireIntervalRemoved(this, original_size - 4, original_size - 1);
384 }
385 else {
386 fireIntervalAdded(this, original_size - 4, original_size - 1);
387 }
388 }
389
390 /** Determine the current separator index. */
391 private int findSeparatorIndex() {
392 int separator_index = super.getSize() - 1;
393 while(separator_index >= 0) {
394 Plugin search = (Plugin) getElementAt(separator_index);
395 if(search.isSeparator()) {
396 return separator_index;
397 }
398 separator_index--;
399 }
400 return separator_index;
401 }
402
403
404 /** Retrieve a list of those plugins that are in library but not in the assigned plugins. */
405 private Object[] getAvailable() {
406 ArrayList available = new ArrayList();
407 int library_size = library.size();
408 for(int i = 0; i < library_size; i++) {
409 Plugin plugin = (Plugin) library.get(i);
410 String plugin_name = plugin.getName();
411 if(!plugin.isAbstract() && !plugin_name.equals(StaticStrings.ARCPLUG_STR) && !plugin_name.equals(StaticStrings.RECPLUG_STR)) {
412 available.add(plugin);
413 }
414 plugin = null;
415 }
416 // Now go through the assigned plugins, and remove any that match.
417 // only for < lib sys specialist mode
418 if (Configuration.getMode()<=Configuration.SYSTEMS_MODE) {
419 available.removeAll(children());
420 }
421 //DebugStream.println("There are a total of " + library.size() + " plugins in the library.");
422 //DebugStream.println("However " + children().size() + " are in use,");
423 //DebugStream.println("So only " + available.size() + " remain.");
424 Collections.sort(available);
425 return available.toArray();
426 }
427
428 /** Method to extract just the plugins name from a file object.
429 * @param plugin The <strong>File</strong> which references a certain plugin.
430 * @return A <strong>String</strong> containing just the plugins name, without extension.
431 */
432 private String getPluginName(String filename) {
433 String name = filename;
434 if(name.indexOf(".") != -1) {
435 name = name.substring(0, name.indexOf("."));
436 }
437 return name;
438 }
439
440
441 /** Method to load the details of a single plug-in.
442 * @param plugin The plugin <strong>File</strong> you wish to load.
443 */
444 private void loadPlugin(String plugin, String lang, String collection_name) {
445 Document document = null;
446 InputStream input_stream = null;
447
448 // Run pluginfo on this plugin, and then send the results for parsing.
449 try {
450 StringBuffer xml = null;
451 if (Gatherer.isGsdlRemote) {
452 String pluginfo_output = RemoteGreenstoneServer.getScriptOptions("pluginfo.pl", "&plugin=" + plugin);
453 xml = new StringBuffer(pluginfo_output);
454 }
455 else {
456 ArrayList args = new ArrayList();
457 if (Utility.isWindows()) {
458 args.add(Configuration.perl_path);
459 args.add("-S");
460 }
461 args.add(LocalGreenstone.getBinScriptDirectoryPath() + "pluginfo.pl");
462 args.add("-xml");
463 args.add("-language");
464 args.add(lang);
465 args.add("-collect");
466 args.add(collection_name);
467 args.add(getPluginName(plugin));
468
469 // Create the process.
470 Runtime runtime = Runtime.getRuntime();
471 Process process = runtime.exec((String[])args.toArray(new String [0]));
472 input_stream = process.getErrorStream();
473 xml = XMLTools.readXMLStream(input_stream);
474 }
475
476 if (xml.length() > 0) {
477 document = CollectionDesignManager.XMLStringToDOM(xml, plugin);
478 }
479 else {
480 JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CDM.PlugInManager.PlugIn_XML_Parse_Failed", plugin), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
481 }
482 }
483 catch (Exception exception) {
484 DebugStream.println("Failed when trying to parse: " + plugin);
485 DebugStream.printStackTrace(exception);
486 }
487
488 if (document != null) {
489 parseXML(document.getDocumentElement());
490 }
491 }
492
493 /** Method to initially load information from the standard plug-ins within the gsdl Perl library.
494 */
495 private void loadPlugins() {
496 // Attempt to restore the cached file.
497 File plugins_dat_file = new File(Gatherer.getGLIUserDirectoryPath() + "plugins.dat");
498 try {
499 FileInputStream file = new FileInputStream(plugins_dat_file);
500 ObjectInputStream input = new ObjectInputStream(file);
501 library = (ArrayList) input.readObject();
502 }
503 catch (Exception error) {
504 DebugStream.println("Unable to open " + plugins_dat_file);
505 }
506
507 if(library == null) {
508 library = new ArrayList();
509
510 if (Gatherer.isGsdlRemote) {
511 String pluginfo_output = RemoteGreenstoneServer.getScriptOptions("pluginfo.pl", "&listall=");
512 loadPlugins(new StringBuffer(pluginfo_output));
513 }
514
515 else {
516 // Retrieve the gsdl home directory...
517 String directory = LocalGreenstone.getDirectoryPath();
518 directory = directory + "perllib" + File.separator + "plugins" + File.separator;
519 String current_lang = Configuration.getLanguage();
520 String collection_name = Gatherer.c_man.getCollection().getName();
521
522 boolean is_windows = Utility.isWindows();
523 boolean is_mac = Utility.isMac();
524
525 File files[] = (new File(directory)).listFiles();
526 File coll_files[] = (new File(Gatherer.c_man.getCollectionPluginsDirectoryPath())).listFiles();
527 int num_files = 0;
528 if (files != null) {
529 num_files += files.length;
530 }
531 if (coll_files != null) {
532 num_files += coll_files.length;
533 }
534 if(num_files > 0) {
535
536 // Create a progress indicator.
537 ParsingProgress progress = new ParsingProgress(Dictionary.get("CDM.PlugInManager.Parsing.Title"), Dictionary.get("CDM.PlugInManager.Parsing.Message"), num_files);
538 if (coll_files != null) {
539 for (int i=0; i<coll_files.length; i++) {
540 if(coll_files[i].getName().endsWith(".pm")) {
541 loadPlugin(coll_files[i].getName(), current_lang, collection_name);
542 }
543 progress.inc();
544 }
545 }
546
547 if (files != null) {
548 for(int i = 0; i < files.length; i++) {
549 // We only want to check Perl Modules.
550 if(files[i].getName().endsWith(".pm")) {
551 if (files[i].getName().equals("GMLPlug.pm") || ((is_windows || is_mac) && files[i].getName().equals("DBPlug.pm"))) {
552 // don't load GMLPlug or DBPlug for windows
553 } else {
554 loadPlugin(files[i].getName(), current_lang, collection_name);
555 }
556 }
557 progress.inc();
558 }
559 }
560 progress.dispose();
561 progress.destroy();
562 progress = null;
563 }
564 }
565 }
566 }
567
568
569 /** Method to load plug-in information from a specified input stream (could be local or through URL). Of course no plug-ins may be found at this location.
570 * @param input_stream An <strong>InputStream</strong> indicating the where list of plugins -- encoded in XML -- can be read from
571 */
572 private void loadPlugins(StringBuffer xml)
573 {
574 Document document = CollectionDesignManager.XMLStringToDOM(xml, "-listall");
575
576 // Parse XML to build up list of plugin names
577 Node root = document.getDocumentElement();
578
579 NamedNodeMap attributes = root.getAttributes();
580 Node length_node = attributes.getNamedItem("length");
581 String num_plugins_str = length_node.getNodeValue();
582 int num_plugins = Integer.parseInt(num_plugins_str);
583 String plugin_list[] = new String[num_plugins];
584
585 Node node = root.getFirstChild();
586 int i = 0;
587 while (node != null) {
588 String node_name = node.getNodeName();
589 if (node_name.equalsIgnoreCase("PluginName")) {
590 String name = XMLTools.getValue(node);
591 plugin_list[i] = name;
592 i++;
593 }
594
595 node = node.getNextSibling();
596 }
597
598
599 boolean is_windows = Utility.isWindows();
600 boolean is_mac = Utility.isMac();
601
602 String current_lang = Configuration.getLanguage();
603 String collection_name = Gatherer.c_man.getCollection().getName();
604 if (num_plugins>0) {
605 // Create a progress indicator.
606 ParsingProgress progress = new ParsingProgress(Dictionary.get("CDM.PlugInManager.Parsing.Title"), Dictionary.get("CDM.PlugInManager.Parsing.Message"), num_plugins);
607
608 for (i=0; i<num_plugins; i++) {
609 String plugin = plugin_list[i];
610 if (plugin.equals("GMLPlug.pm") || ((is_windows || is_mac) && plugin.equals("DBPlug.pm"))) {
611 // don't load GMLPlug or DBPlug for windows
612 } else {
613 loadPlugin(plugin, current_lang, collection_name);
614 }
615
616 progress.inc();
617 }
618 progress.dispose();
619 progress.destroy();
620 progress = null;
621 }
622 }
623
624
625 private Plugin parseXML(Node root) {
626 Plugin plugin = new Plugin();
627 String node_name = null;
628 for (Node node = root.getFirstChild(); node != null; node = node.getNextSibling()) {
629 node_name = node.getNodeName();
630 if(node_name.equalsIgnoreCase("Name")) {
631 String name = XMLTools.getValue(node);
632 // We can save ourselves some processing time if a plugin with this name already exists in our manager. If so retrieve it and return it.
633 Plugin existing = getBasePlugin(name);
634 if(existing != null) {
635 return existing;
636 }
637 plugin.setName(name);
638 }
639 else if (node_name.equalsIgnoreCase("Desc")) {
640 plugin.setDescription(XMLTools.getValue(node));
641 }
642 else if (node_name.equalsIgnoreCase("Abstract")) {
643 plugin.setIsAbstract(XMLTools.getValue(node).equalsIgnoreCase(StaticStrings.YES_STR));
644 }
645 else if (node_name.equalsIgnoreCase("Explodes")) {
646 plugin.setDoesExplodeMetadataDatabases(XMLTools.getValue(node).equalsIgnoreCase(StaticStrings.YES_STR));
647 //System.err.println("Plugin " + plugin.getName() + " explodes metadata databases: " + plugin.doesExplodeMetadataDatabases());
648 }
649 // Parse the multitude of arguments
650 else if(node_name.equalsIgnoreCase("Arguments")) {
651 for(Node arg = node.getFirstChild(); arg != null; arg = arg.getNextSibling()) {
652 node_name = arg.getNodeName();
653 // An option.
654 if(node_name.equalsIgnoreCase("Option")) {
655 Argument argument = new Argument();
656 argument.parseXML((Element)arg);
657 plugin.addArgument(argument);
658 }
659 }
660 }
661 // A super plugin class.
662 else if(node_name.equalsIgnoreCase("PlugInfo")) {
663 Plugin super_plugin = parseXML(node);
664 plugin.setSuper(super_plugin);
665 }
666
667 }
668 if(plugin.getName() != null) {
669 addPlugin(plugin);
670 return plugin;
671 }
672 return null;
673 }
674
675 /** A class which provodes controls for assigned and editing plugins. */
676 private class PluginControl
677 extends JPanel
678 implements Control {
679 /** Button for adding plugins. */
680 private JButton add = null;
681 /** Button for configuring the selected plugin. */
682 private JButton configure = null;
683 /** Button to move an assigned plugin one position lower in the order. */
684 private JButton move_down_button = null;
685 /** Button to move an assigned plugin one position higher in the order. */
686 private JButton move_up_button = null;
687 /** Button to remove the selected plugin. */
688 private JButton remove = null;
689 /** A combobox containing all of the known plugins, including those that may have already been assigned. */
690 private JComboBox plugin_combobox = null;
691 /** The label next to the plugin combobox. */
692 private JLabel plugin_label = null;
693 /** The label above the assigned plugin list. */
694 private JLabel plugin_list_label = null;
695 /** A list of assigned plugins. */
696 private JList plugin_list = null;
697 /** The area where the add, configure and remove buttons are placed. */
698 private JPanel button_pane = null;
699 /** The region which divides the central portion of the view into list and controls */
700 private JPanel central_pane = null;
701 /** The area where movement buttons are placed. */
702 private JPanel movement_pane = null;
703 /** The small region containing the plugin combobox and its label. */
704 private JPanel plugin_pane = null;
705 /** The pane containing the assigned plugin list and its label. */
706 private JPanel plugin_list_pane = null;
707
708 /** Constructor.
709 */
710 public PluginControl() {
711 // Create
712 add = new GLIButton(Dictionary.get("CDM.PlugInManager.Add"), Dictionary.get("CDM.PlugInManager.Add_Tooltip"));
713
714 button_pane = new JPanel();
715 central_pane = new JPanel();
716
717 configure = new GLIButton(Dictionary.get("CDM.PlugInManager.Configure"), Dictionary.get("CDM.PlugInManager.Configure_Tooltip"));
718 configure.setEnabled(false);
719
720 JPanel header_pane = new DesignPaneHeader("CDM.GUI.Plugins", "plugins");
721 move_up_button = new GLIButton(Dictionary.get("CDM.Move.Move_Up"), JarTools.getImage("arrow-up.gif"), Dictionary.get("CDM.Move.Move_Up_Tooltip"));
722 move_up_button.setEnabled(false);
723
724 move_down_button = new GLIButton(Dictionary.get("CDM.Move.Move_Down"), JarTools.getImage("arrow-down.gif"), Dictionary.get("CDM.Move.Move_Down_Tooltip"));
725 move_down_button.setEnabled(false);
726
727 movement_pane = new JPanel();
728
729 PluginComboboxListener picl = new PluginComboboxListener();
730 plugin_combobox = new JComboBox(getAvailable());
731 plugin_combobox.setEditable(false);
732 picl.itemStateChanged(new ItemEvent(plugin_combobox, 0, null, ItemEvent.SELECTED));
733
734 plugin_label = new JLabel(Dictionary.get("CDM.PlugInManager.PlugIn"));
735
736 plugin_list = new JList(model);
737 plugin_list.setCellRenderer(new ListRenderer());
738 plugin_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
739 plugin_list_label = new JLabel(Dictionary.get("CDM.PlugInManager.Assigned"));
740 //plugin_list_label.setHorizontalAlignment(JLabel.CENTER);
741 plugin_list_label.setOpaque(true);
742
743 plugin_list_pane = new JPanel();
744 plugin_pane = new JPanel();
745
746 remove = new GLIButton(Dictionary.get("CDM.PlugInManager.Remove"), Dictionary.get("CDM.PlugInManager.Remove_Tooltip"));
747 remove.setEnabled(false);
748
749 // Listeners
750 add.addActionListener(new AddListener()); //all_change_listener is listening to the ArgumentConfiguration
751 configure.addActionListener(new ConfigureListener());
752 MoveListener ml = new MoveListener();
753 move_down_button.addActionListener(ml);
754 move_down_button.addActionListener(CollectionDesignManager.all_change_listener);
755 move_up_button.addActionListener(ml);
756 move_up_button.addActionListener(CollectionDesignManager.all_change_listener);
757 plugin_combobox.addItemListener(picl);
758 remove.addActionListener(new RemoveListener());
759 remove.addActionListener(CollectionDesignManager.all_change_listener);
760 plugin_list.addMouseListener(new ClickListener());
761 plugin_list.addListSelectionListener(new ListListener());
762 picl = null;
763
764 // Layout
765 movement_pane.setBorder(BorderFactory.createEmptyBorder(0,2,0,0));
766 movement_pane.setLayout(new GridLayout(4,1));
767 movement_pane.add(move_up_button);
768 movement_pane.add(new JPanel());
769 movement_pane.add(new JPanel());
770 movement_pane.add(move_down_button);
771
772 plugin_list_pane.setLayout(new BorderLayout());
773 plugin_list_pane.add(plugin_list_label, BorderLayout.NORTH);
774 plugin_list_pane.add(new JScrollPane(plugin_list), BorderLayout.CENTER);
775 modeChanged(Configuration.getMode()); // Whether the movement buttons are visible is mode dependant
776
777 plugin_label.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
778
779 plugin_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,0));
780 plugin_pane.setLayout(new BorderLayout(5,0));
781 plugin_pane.add(plugin_label, BorderLayout.WEST);
782 plugin_pane.add(plugin_combobox, BorderLayout.CENTER);
783
784 button_pane.setLayout(new GridLayout(1,3));
785 button_pane.add(add);
786 button_pane.add(configure);
787 button_pane.add(remove);
788
789 // Scope these mad bordering skillz.
790 JPanel temp = new JPanel(new BorderLayout());
791 temp.add(plugin_pane, BorderLayout.NORTH);
792 temp.add(button_pane, BorderLayout.SOUTH);
793
794 central_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
795 central_pane.setLayout(new BorderLayout());
796 central_pane.add(plugin_list_pane, BorderLayout.CENTER);
797 central_pane.add(temp, BorderLayout.SOUTH);
798
799 setBorder(BorderFactory.createEmptyBorder(0,5,0,0));
800 setLayout(new BorderLayout());
801 add(header_pane, BorderLayout.NORTH);
802 add(central_pane, BorderLayout.CENTER);
803 }
804
805 /** Method which acts like a destructor, tidying up references to persistant objects.
806 */
807 public void destroy() {
808 }
809
810 /** This method is overridden to ensure the instructions are scrolled to top, before the super classes updateUI() is called.
811 no longer have instructions, do we still need updateUI???
812 */
813 public void gainFocus() {
814 super.updateUI();
815 }
816
817 public void loseFocus() {
818 }
819
820 /** The current detail mode controls two aspects of plugin manager: whether the movement buttons are visible and whether the fixed position plugins Arc and RecPlug are in the list
821 * @param mode the current mode as an int, which can be matched against static ints in the Configuration class
822 */
823 public void modeChanged(int mode) {
824 // First of all we clear the current selection, as there can be some serious problems if the user selects the plugins we're hiding, or had the last plugin selected before we unhid the last three
825 plugin_list.clearSelection();
826 // The first change is dependant on whether the user is systems mode or higher
827 if(mode >= Configuration.SYSTEMS_MODE) {
828 // Show movement buttons
829 plugin_list_pane.add(movement_pane, BorderLayout.EAST);
830 // Do we show Arc and RecPlugs or hide them and the separator line
831 setHideLines(!(mode >= Configuration.EXPERT_MODE));
832 }
833 // Otherwise hide the movement buttons and fixed plugins
834 else {
835 plugin_list_pane.remove(movement_pane);
836 setHideLines(true);
837 }
838 plugin_list_pane.updateUI();
839 }
840
841 /** This class listens for actions upon the add button in the controls, and if detected calls the <i>assignPlugin()</i> method. */
842 private class AddListener
843 implements ActionListener {
844 /** Any implementation of <i>ActionListener</i> must include this method so that we can be informed when an action has occured on one of our target controls.
845 * @param event An <strong>ActionEvent</strong> containing information garnered from the control action.
846 */
847 public void actionPerformed(ActionEvent event) {
848 Object selected_object = plugin_combobox.getSelectedItem();
849 if(selected_object != null) {
850 // Retrieve the base plugin if any
851 Plugin base_plugin = getBasePlugin(selected_object.toString());
852
853 // Create a new element in the DOM
854 Element element = CollectionDesignManager.collect_config.document.createElement(CollectionConfiguration.PLUGIN_ELEMENT);
855 element.setAttribute(CollectionConfiguration.TYPE_ATTRIBUTE, base_plugin.getName());
856 Plugin new_plugin = new Plugin(element, base_plugin);
857 element = null;
858
859 // Automatically chain to configuration. This ensures required arguments are filled out.
860 ArgumentConfiguration ac = new ArgumentConfiguration(new_plugin);
861 if(ac.display()) {
862 assignPlugin(new_plugin);
863 plugin_list.setSelectedValue(new_plugin, true);
864 // Since we weren't cancelled, if we are in a low mode, remove the plugin from the available list (except for UnknownPlug
865 if(base_plugin != null && Configuration.getMode() <= Configuration.SYSTEMS_MODE && !base_plugin.getName().equals(StaticStrings.UNKNOWNPLUG_STR)) {
866 plugin_combobox.removeItem(base_plugin);
867 plugin_combobox.setSelectedIndex(0);
868 }
869 }
870 ac = null;
871 new_plugin = null;
872 base_plugin = null;
873 }
874 }
875 }
876
877 /** Listens for double clicks apon the list and react as if the configure button was pushed. */
878 private class ClickListener
879 extends MouseAdapter {
880 /** Called whenever the mouse is clicked over a registered component, we use this to chain through to the configure prompt.
881 * @param event A <strong>MouseEvent</strong> containing information about the mouse click.
882 */
883 public void mouseClicked(MouseEvent event) {
884 if(event.getClickCount() == 2 ) {
885 if(!plugin_list.isSelectionEmpty()) {
886 Plugin plugin = (Plugin) plugin_list.getSelectedValue();
887 if(!plugin.isSeparator()) {
888 ArgumentConfiguration ac = new ArgumentConfiguration(plugin);
889 if(ac.display()) {
890 refresh(plugin);
891 }
892 ac.destroy();
893 ac = null;
894 // cos I can't be bothered checking every argument to see if it has changed or not, we'll asasume that the configuration has changed if someone has clicked configure
895 Gatherer.c_man.configurationChanged();
896 }
897 }
898 }
899 }
900 }
901
902 /** This class listens for actions upon the configure button in the controls, and if detected creates a new <strong>ArgumentConfiguration</strong> dialog box to allow for configuration.
903 * @see org.greenstone.gatherer.cdm.ArgumentConfiguration
904 */
905 private class ConfigureListener
906 implements ActionListener {
907 /** Any implementation of <i>ActionListener</i> must include this method so that we can be informed when an action has occured on one of our target controls.
908 * @param event An <strong>ActionEvent</strong> containing information garnered from the control action.
909 */
910 public void actionPerformed(ActionEvent event) {
911 if(!plugin_list.isSelectionEmpty()) {
912 Plugin plugin = (Plugin) plugin_list.getSelectedValue();
913 if(!plugin.isSeparator()) {
914 ArgumentConfiguration ac = new ArgumentConfiguration(plugin);
915 if(ac.display()) {
916 refresh(plugin);
917 }
918 ac.destroy();
919 ac = null;
920 // cos I can't be bothered checking every argument to see if it has changed or not, we'll asasume that the configuration has changed if someone has clicked configure
921 Gatherer.c_man.configurationChanged();
922 }
923 }
924 }
925 }
926
927 /** listens for changes in the list selection and enables the configure and remove buttons if there is a selection, disables them if there is no selection */
928 private class ListListener
929 implements ListSelectionListener {
930
931 public void valueChanged(ListSelectionEvent e) {
932 if (!e.getValueIsAdjusting()) { // we get two events for one change in list selection - use the false one (the second one)
933 if (plugin_list.isSelectionEmpty()) {
934 move_up_button.setEnabled(false);
935 move_down_button.setEnabled(false);
936 configure.setEnabled(false);
937 remove.setEnabled(false);
938 }
939 else {
940 Plugin selected_plugin = (Plugin) plugin_list.getSelectedValue();
941 if(selected_plugin.isSeparator()) {
942 move_up_button.setEnabled(false);
943 move_down_button.setEnabled(false);
944 configure.setEnabled(false);
945 remove.setEnabled(false);
946 }
947 else {
948 configure.setEnabled(true);
949 String plugin_name = selected_plugin.getName();
950 // Some buttons are only available for plugins other than ArcPlug and RecPlug
951 if(plugin_name.equals(StaticStrings.ARCPLUG_STR) || plugin_name.equals(StaticStrings.RECPLUG_STR) ) {
952 move_up_button.setEnabled(false);
953 move_down_button.setEnabled(false);
954 remove.setEnabled(false);
955 }
956 else {
957 // don't let people remove special plugins such GAPlug an METSPlug,
958 // unless they are in systems mode or above
959 int mode = Configuration.getMode();
960 for (int i=0; i<StaticStrings.KEEP_PLUG.length; i++) {
961 if ((plugin_name.equals(StaticStrings.KEEP_PLUG[i])) &&
962 (mode < Configuration.SYSTEMS_MODE)) {
963 remove.setEnabled(false);
964 break;
965 } else {
966 remove.setEnabled(true);
967 }
968 }
969
970 // Move ups are only enabled if the selected plugin isn't already at the top
971 Plugin first_plugin = (Plugin) getElementAt(0);
972 if(!first_plugin.equals(selected_plugin)) {
973 move_up_button.setEnabled(true);
974 }
975 else {
976 move_up_button.setEnabled(false);
977 }
978 // And move downs are only allowed when the selected plugin isn't at an index one less than the separator line.
979 int separator_index = findSeparatorIndex();
980 int selected_index = plugin_list.getSelectedIndex();
981 if(selected_index < separator_index - 1) {
982 move_down_button.setEnabled(true);
983 }
984 else {
985 move_down_button.setEnabled(false);
986 }
987 }
988 selected_plugin = null;
989 plugin_name = null;
990 }
991 }
992 }
993 }
994 }
995
996 /** A special list renderer which is able to render separating lines as well. */
997 private class ListRenderer
998 extends DefaultListCellRenderer {
999 /** Return a component that has been configured to display the specified value. That component's paint method is then called to "render" the cell. If it is necessary to compute the dimensions of a list because the list cells do not have a fixed size, this method is called to generate a component on which getPreferredSize can be invoked.
1000 * @param list - The <strong>JList</strong> we're painting.
1001 * @param value - The value returned by list.getModel().getElementAt(index) as an <strong>Object</strong>.
1002 * @param index - The cells index as an <i>int</i>.
1003 * @param isSelected - <i>true</i> if the specified cell was selected.
1004 * @param cellHasFocus - <i>true</i> if the specified cell has the focus.
1005 * @return A <strong>Component</strong> whose paint() method will render the specified value.
1006 * @see javax.swing.JList
1007 * @see javax.swing.JSeparator
1008 * @see javax.swing.ListModel
1009 * @see javax.swing.ListSelectionModel
1010 */
1011 public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
1012 Plugin plugin = (Plugin) value;
1013 if(plugin.isSeparator()) {
1014 return separator;
1015 }
1016 else {
1017 return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
1018 }
1019 }
1020 }
1021
1022
1023 /** Listens for actions apon the move buttons in the manager controls, and if detected calls the <i>movePlugin()</i> method of the manager with the appropriate details. */
1024 private class MoveListener
1025 implements ActionListener {
1026 /** Any implementation of <i>ActionListener</i> must include this method so that we can be informed when an action has occured on one of our target controls.
1027 * @param event An <strong>ActionEvent</strong> containing information garnered from the control action.
1028 */
1029 public void actionPerformed(ActionEvent event) {
1030 if (!plugin_list.isSelectionEmpty()) {
1031 Object object = plugin_list.getSelectedValue();
1032 if (object instanceof Plugin) {
1033 Plugin plugin = (Plugin) object;
1034 if (event.getSource() == move_up_button) {
1035 movePlugin(plugin, true, false);
1036 }
1037 else if (event.getSource() == move_down_button) {
1038 movePlugin(plugin, false, false);
1039 }
1040 plugin_list.setSelectedValue(plugin, true);
1041 }
1042 }
1043 }
1044 }
1045
1046 /** This listener reacts to changes in the current selection of the plugin combobox. */
1047 private class PluginComboboxListener
1048 implements ItemListener {
1049 /** When a user selects a certain plugin, update the tooltip to show the plugin description. */
1050 public void itemStateChanged(ItemEvent event) {
1051 if(event.getStateChange() == ItemEvent.SELECTED) {
1052 // Retrieve the selected plugin
1053 Object current_selection = plugin_combobox.getSelectedItem();
1054 // And reset the tooltip. If the plugin is null or is a string, then go back to the default message
1055 if(current_selection == null || current_selection instanceof String) {
1056 plugin_combobox.setToolTipText(Dictionary.get("CDM.PlugInManager.PlugIn_Tooltip"));
1057 }
1058 else {
1059 Plugin current_plugin = (Plugin) current_selection;
1060 plugin_combobox.setToolTipText(Utility.formatHTMLWidth(current_plugin.getDescription(), 40));
1061 current_plugin = null;
1062 }
1063 current_selection = null;
1064 }
1065 }
1066 }
1067
1068 /** This class listens for actions upon the remove button in the controls, and if detected calls the <i>removePlugin()</i> method.
1069 */
1070 private class RemoveListener
1071 implements ActionListener {
1072 /** Any implementation of <i>ActionListener</i> must include this method so that we can be informed when an action has occured on one of our target controls.
1073 * @param event An <strong>ActionEvent</strong> containing information garnered from the control action.
1074 */
1075 public void actionPerformed(ActionEvent event) {
1076 int selected_index = plugin_list.getSelectedIndex();
1077 if(selected_index != -1) {
1078 Plugin selected_plugin = (Plugin) plugin_list.getSelectedValue();
1079 removePlugin(selected_plugin);
1080 selected_plugin = null;
1081 // Select the next plugin if available
1082 if(selected_index < plugin_list.getModel().getSize()) {
1083 // If the new selection is above the separator we can remove it
1084 if(selected_index < findSeparatorIndex()) {
1085 plugin_list.setSelectedIndex(selected_index);
1086
1087 // don't let people remove special plugins such GAPlug an METSPlug,
1088 // unless they are in systems mode or above
1089 int mode = Configuration.getMode();
1090 for (int i=0; i<StaticStrings.KEEP_PLUG.length; i++) {
1091 String selected_plugin_name
1092 = ((Plugin)plugin_list.getSelectedValue()).getName();
1093 if ((selected_plugin_name.equals(StaticStrings.KEEP_PLUG[i])) &&
1094 (mode < Configuration.SYSTEMS_MODE)) {
1095 remove.setEnabled(false);
1096 break;
1097 } else {
1098 remove.setEnabled(true);
1099 }
1100 }
1101 }
1102 // Otherwise select the first non-removable plugin
1103 else {
1104 plugin_list.setSelectedIndex(selected_index + 1);
1105 remove.setEnabled(false);
1106 }
1107 }
1108 else {
1109 remove.setEnabled(false);
1110 }
1111 // Refresh the available plugins
1112 plugin_combobox.setModel(new DefaultComboBoxModel(getAvailable()));
1113 }
1114 else {
1115 remove.setEnabled(false);
1116 }
1117 }
1118 }
1119 }
1120
1121
1122 private class PluginSuggestionPrompt
1123 extends ModalDialog
1124 implements ActionListener
1125 {
1126 private Dimension size = new Dimension(480, 240);
1127 private GComboBox suitable_plugins_combobox = null;
1128 private GLIButton add_button = null;
1129 private GLIButton ignore_button = null;
1130
1131 public PluginSuggestionPrompt(String filename, ArrayList suitable_plugins)
1132 {
1133 super(Gatherer.g_man, true);
1134 setModal(true);
1135 setSize(size);
1136 setTitle(Dictionary.get("CDM.PluginManager.SuggestedPluginListTitle"));
1137
1138 String[] args = new String[1];
1139 args[0] = filename;
1140
1141 JTextArea instructions_textarea = new JTextArea(Dictionary.get("CDM.PluginManager.Plugin_Suggestion_Prompt", args));
1142 instructions_textarea.setCaretPosition(0);
1143 instructions_textarea.setEditable(false);
1144 instructions_textarea.setLineWrap(true);
1145 instructions_textarea.setRows(5);
1146 instructions_textarea.setWrapStyleWord(true);
1147
1148 JLabel suitable_plugins_label = new JLabel(Dictionary.get("CDM.PlugInManager.PlugIn"));
1149 suitable_plugins_label.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
1150
1151 suitable_plugins_combobox = new GComboBox(suitable_plugins);
1152 suitable_plugins_combobox.setBackgroundNonSelectionColor(Configuration.getColor("coloring.editable_background", false));
1153 suitable_plugins_combobox.setBackgroundSelectionColor(Configuration.getColor("coloring.collection_selection_background", false));
1154 suitable_plugins_combobox.setTextNonSelectionColor(Configuration.getColor("coloring.workspace_tree_foreground", false));
1155 suitable_plugins_combobox.setTextSelectionColor(Configuration.getColor("coloring.collection_selection_foreground", false));
1156
1157 JPanel suitable_plugins_pane = new JPanel();
1158 //suitable_plugins_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,0));
1159 suitable_plugins_pane.setLayout(new BorderLayout(5,0));
1160 suitable_plugins_pane.add(suitable_plugins_label, BorderLayout.WEST);
1161 suitable_plugins_pane.add(suitable_plugins_combobox, BorderLayout.CENTER);
1162
1163 add_button = new GLIButton(Dictionary.get("CDM.PlugInManager.QuickAdd"), Dictionary.get("CDM.PlugInManager.Add_Tooltip"));
1164 ignore_button = new GLIButton(Dictionary.get("CDM.PlugInManager.Ignore"), Dictionary.get("CDM.PlugInManager.Ignore_Tooltip"));
1165
1166 add_button.addActionListener(this);
1167 ignore_button.addActionListener(this);
1168
1169 JPanel button_pane = new JPanel();
1170 button_pane.setLayout(new GridLayout(1,2,5,0));
1171 button_pane.add(add_button);
1172 button_pane.add(ignore_button);
1173
1174 JPanel controls_pane = new JPanel();
1175 controls_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
1176 controls_pane.setLayout(new GridLayout(2,1,0,5));
1177 controls_pane.add(suitable_plugins_pane);
1178 controls_pane.add(button_pane);
1179
1180 JPanel content_pane = (JPanel) getContentPane();
1181 content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
1182 content_pane.setLayout(new BorderLayout());
1183 content_pane.add(instructions_textarea, BorderLayout.CENTER);
1184 content_pane.add(controls_pane, BorderLayout.SOUTH);
1185
1186 // Show
1187 Dimension screen_size = Configuration.screen_size;
1188 setLocation((screen_size.width - size.width) / 2, (screen_size.height - size.height) / 2);
1189 setVisible(true);
1190 }
1191
1192 public void actionPerformed(ActionEvent event) {
1193
1194 if(event.getSource() == add_button) {
1195 // add the selected plugin to the list
1196 Object selected_object = suitable_plugins_combobox.getSelectedItem();
1197 Plugin base_plugin = getBasePlugin(selected_object.toString());
1198
1199 // Create a new element in the DOM
1200 Element element = CollectionDesignManager.collect_config.document.createElement(CollectionConfiguration.PLUGIN_ELEMENT);
1201 // Remember that the plugin supplied might be a custom string rather than a base plugin
1202 Plugin new_plugin = null;
1203 if(base_plugin != null) {
1204 //DebugStream.println("New Plugin based on existing Plugin");
1205 element.setAttribute(CollectionConfiguration.TYPE_ATTRIBUTE, base_plugin.getName());
1206 new_plugin = new Plugin(element, base_plugin);
1207 }
1208 else {
1209 //DebugStream.println("New Custom Plugin");
1210 element.setAttribute(CollectionConfiguration.TYPE_ATTRIBUTE, selected_object.toString());
1211 new_plugin = new Plugin(element, null);
1212 }
1213 assignPlugin(new_plugin);
1214 } // else do nothing
1215
1216 // close the dialog
1217 setVisible(false);
1218 }
1219
1220 }
1221
1222
1223 /** Creates a list separator.
1224 * Found on Google Groups. Code courtesy of Paul Farwell.
1225 */
1226 private JPanel getSeparator() {
1227 // We put the separator inside a panel to control its appearance
1228 JPanel _sepPanel = new JPanel();
1229 _sepPanel.setOpaque(false);
1230 _sepPanel.setBorder(BorderFactory.createEmptyBorder(1, 3, 1, 3));
1231 _sepPanel.setLayout(new BoxLayout(_sepPanel, BoxLayout.Y_AXIS));
1232 _sepPanel.add(Box.createRigidArea(new Dimension(0, 4)));
1233 // We have to be a little careful here, as the default UI for separators under MacOS is a blank box. Instead we force a BasicUI look
1234 _sepPanel.add(new BasicSeparator());
1235 _sepPanel.add(Box.createRigidArea(new Dimension(0, 4)));
1236 return _sepPanel;
1237 }
1238
1239 /** This class behaves just like a normal JSeparator except that, no matter what the current settings in the UIManager are, it always paints itself with BasicSeparatorUI. */
1240 private class BasicSeparator
1241 extends JSeparator {
1242
1243 private ComponentUI basic_ui;
1244
1245 public BasicSeparator() {
1246 super();
1247 basic_ui = new BasicSeparatorUI();
1248 }
1249
1250 public void paintComponent(Graphics g) {
1251 if (basic_ui != null) {
1252 basic_ui.update(g, this);
1253 }
1254 }
1255 }
1256}
Note: See TracBrowser for help on using the repository browser.