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 | */
|
---|
27 | package org.greenstone.gatherer.cdm;
|
---|
28 |
|
---|
29 | import java.awt.*;
|
---|
30 | import java.awt.event.*;
|
---|
31 | import java.io.*;
|
---|
32 | import java.util.*;
|
---|
33 | import javax.swing.*;
|
---|
34 | import javax.swing.event.*;
|
---|
35 | import javax.swing.plaf.basic.*;
|
---|
36 | import org.apache.xerces.parsers.*;
|
---|
37 | import org.greenstone.gatherer.Dictionary;
|
---|
38 | import org.greenstone.gatherer.Gatherer;
|
---|
39 | import org.greenstone.gatherer.cdm.Argument;
|
---|
40 | import org.greenstone.gatherer.cdm.ArgumentConfiguration;
|
---|
41 | import org.greenstone.gatherer.cdm.CollectionDesignManager;
|
---|
42 | import org.greenstone.gatherer.cdm.CommandTokenizer;
|
---|
43 | import org.greenstone.gatherer.cdm.Control;
|
---|
44 | import org.greenstone.gatherer.cdm.PlugIn;
|
---|
45 | import org.greenstone.gatherer.gui.DoubleImageButton;
|
---|
46 | import org.greenstone.gatherer.gui.GComboBox;
|
---|
47 | import org.greenstone.gatherer.msm.MSMUtils;
|
---|
48 | import org.greenstone.gatherer.util.StaticStrings;
|
---|
49 | import org.greenstone.gatherer.util.Utility;
|
---|
50 | import org.w3c.dom.*;
|
---|
51 | import org.xml.sax.*;
|
---|
52 | /** This class is for maintaining a list of known plug-ins, and importing new plugins using the parser. */
|
---|
53 | public class PlugInManager
|
---|
54 | extends DOMProxyListModel {
|
---|
55 | /** The library 'reserve' of base plugins. */
|
---|
56 | private ArrayList library = null;
|
---|
57 | /** The controls for editing the contents of this manager. */
|
---|
58 | private Control controls = null;
|
---|
59 | private DOMProxyListModel model;
|
---|
60 | private JPanel separator;
|
---|
61 | private PlugIn separator_plugin;
|
---|
62 | /** The default size for a label. */
|
---|
63 | static final private Dimension LABEL_SIZE = new Dimension(125, 25);
|
---|
64 | /** Constructor.
|
---|
65 | */
|
---|
66 | public PlugInManager() {
|
---|
67 | super(CollectionDesignManager.collect_config.getDocumentElement(), CollectionConfiguration.PLUGIN_ELEMENT, new PlugIn());
|
---|
68 | Gatherer.println("PlugInManager: " + getSize() + " plugins parsed.");
|
---|
69 | model = this;
|
---|
70 | // Reload/Create the library
|
---|
71 | loadPlugIns();
|
---|
72 | savePlugIns();
|
---|
73 | // Create the separator, cause we can reuse it.
|
---|
74 | separator = getSeparator();
|
---|
75 | }
|
---|
76 |
|
---|
77 | /** Method to add a new plugin to the library
|
---|
78 | * @param plugin the new base PlugIn
|
---|
79 | */
|
---|
80 | public void addPlugIn(PlugIn plugin) {
|
---|
81 | if(!library.contains(plugin)) {
|
---|
82 | library.add(plugin);
|
---|
83 | }
|
---|
84 | }
|
---|
85 |
|
---|
86 | /** Method to assign a plugin
|
---|
87 | * @param plugin the PlugIn to assign
|
---|
88 | */
|
---|
89 | public void assignPlugIn(PlugIn plugin) {
|
---|
90 | if(plugin.getName().equals(StaticStrings.RECPLUG_STR) || plugin.getName().equals(StaticStrings.ARCPLUG_STR)) {
|
---|
91 | addAfter(plugin, separator_plugin); // Adds after separator
|
---|
92 | }
|
---|
93 | else {
|
---|
94 | addBefore(plugin, separator_plugin);
|
---|
95 | }
|
---|
96 | Gatherer.c_man.configurationChanged();
|
---|
97 | }
|
---|
98 |
|
---|
99 | /** Destructor. */
|
---|
100 | public void destroy() {
|
---|
101 | if(controls != null) {
|
---|
102 | controls.destroy();
|
---|
103 | controls = null;
|
---|
104 | }
|
---|
105 | library.clear();
|
---|
106 | library = null;
|
---|
107 | }
|
---|
108 |
|
---|
109 | /** Method to retrieve the control for this manager.
|
---|
110 | * @return the Control
|
---|
111 | */
|
---|
112 | public Control getControls() {
|
---|
113 | if(controls == null) {
|
---|
114 | // Build controls
|
---|
115 | controls = new PlugInControl();
|
---|
116 | }
|
---|
117 | return controls;
|
---|
118 | }
|
---|
119 |
|
---|
120 | /** Retrieve the base pluging of the given name, or null if no such plugin.
|
---|
121 | * @param name the name of the base plugin to retrieve as a String
|
---|
122 | * @return the PlugIn requested or null if no such plugin
|
---|
123 | */
|
---|
124 | public PlugIn getBasePlugIn(String name) {
|
---|
125 | int library_size = library.size();
|
---|
126 | for(int i = 0; i < library_size; i++) {
|
---|
127 | PlugIn plugin = (PlugIn) library.get(i);
|
---|
128 | if(plugin.getName().equals(name)) {
|
---|
129 | return plugin;
|
---|
130 | }
|
---|
131 | }
|
---|
132 | // No success.
|
---|
133 | return null;
|
---|
134 | }
|
---|
135 |
|
---|
136 | /** Method to move a plugin in the list order.
|
---|
137 | * @param plugin the PlugIn you want to move.
|
---|
138 | * @param direction true to move the plugin up, false to move it down.
|
---|
139 | * @param all true to move to move all the way, false for a single step.
|
---|
140 | */
|
---|
141 | public void movePlugIn(PlugIn plugin, boolean direction, boolean all) {
|
---|
142 | // Can't ever move RecPlug or ArcPlug.
|
---|
143 | if(getSize() < 3) {
|
---|
144 | //Gatherer.println("Not enough plugins to allow moving.");
|
---|
145 | return;
|
---|
146 | }
|
---|
147 | if(plugin.getName().equals(StaticStrings.ARCPLUG_STR) || plugin.getName().equals(StaticStrings.RECPLUG_STR)) {
|
---|
148 | JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CDM.Move.Fixed"), Dictionary.get("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE);
|
---|
149 | return;
|
---|
150 | }
|
---|
151 | if(all) {
|
---|
152 | // Move to top
|
---|
153 | if(direction) {
|
---|
154 | // Remove the moving plugin
|
---|
155 | remove(plugin);
|
---|
156 | // Retrieve the first plugin
|
---|
157 | PlugIn first_plugin = (PlugIn) getElementAt(0);
|
---|
158 | // Add the moving plugin before the first plugin
|
---|
159 | addBefore(plugin, first_plugin);
|
---|
160 | first_plugin = null;
|
---|
161 | Gatherer.c_man.configurationChanged();
|
---|
162 | }
|
---|
163 | else {
|
---|
164 | // Remove the moving plugin
|
---|
165 | remove(plugin);
|
---|
166 | // Locate the plugin immediately before the separator. We have to ensure the separator index is up to date, given we've just removed a plugin.
|
---|
167 | int separator_index = -1;
|
---|
168 | if((separator_index = findSeparatorIndex()) != -1) {
|
---|
169 | PlugIn separator_plugin = (PlugIn) getElementAt(separator_index);
|
---|
170 | // Add the moving plugin before the separator
|
---|
171 | addBefore(plugin, separator_plugin);
|
---|
172 | Gatherer.c_man.configurationChanged();
|
---|
173 | }
|
---|
174 | // Otherwise we aren't moving anywhere!
|
---|
175 | }
|
---|
176 | }
|
---|
177 | else {
|
---|
178 | // Try to move the plugin one step in the desired direction.
|
---|
179 | int index = indexOf(plugin);
|
---|
180 | ///ystem.err.println("Index of " + plugin + " = " + index);
|
---|
181 | if(direction) {
|
---|
182 | index--;
|
---|
183 | if(index < 0) {
|
---|
184 | String args[] = new String[2];
|
---|
185 | args[0] = Dictionary.get("CDM.PlugInManager.PlugIn_Str");
|
---|
186 | args[1] = plugin.getName();
|
---|
187 | JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CDM.Move.At_Top", args), Dictionary.get("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE);
|
---|
188 | return;
|
---|
189 | }
|
---|
190 | remove(plugin);
|
---|
191 | add(index, plugin);
|
---|
192 | Gatherer.c_man.configurationChanged();
|
---|
193 | }
|
---|
194 | else {
|
---|
195 | index++;
|
---|
196 | PlugIn next_plugin = (PlugIn) getElementAt(index);
|
---|
197 | if(next_plugin.isSeparator()) {
|
---|
198 | String args[] = new String[1];
|
---|
199 | args[0] = plugin.getName();
|
---|
200 | JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CDM.Move.Cannot", args), Dictionary.get("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE);
|
---|
201 | // Still not going to move RecPlug or ArcPlug.
|
---|
202 | return;
|
---|
203 | }
|
---|
204 | remove(plugin);
|
---|
205 | add(index, plugin);
|
---|
206 | Gatherer.c_man.configurationChanged();
|
---|
207 | }
|
---|
208 | }
|
---|
209 | }
|
---|
210 |
|
---|
211 | /** 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.
|
---|
212 | */
|
---|
213 | public void placeSeparator() {
|
---|
214 | ///ystem.err.println("Placing separator.");
|
---|
215 | int separator_index = getSize();
|
---|
216 | if(separator_index > 0) {
|
---|
217 | boolean found_fixed = false;
|
---|
218 | int index = separator_index - 1;
|
---|
219 | while(index > 0) {
|
---|
220 | PlugIn plugin = (PlugIn) getElementAt(index);
|
---|
221 | String name = plugin.getName();
|
---|
222 | if(name.equals(StaticStrings.RECPLUG_STR) || name.equals(StaticStrings.ARCPLUG_STR)) {
|
---|
223 | found_fixed = true;
|
---|
224 | index--;
|
---|
225 | }
|
---|
226 | else {
|
---|
227 | if(found_fixed) {
|
---|
228 | separator_index = index + 1;
|
---|
229 | index = -1;
|
---|
230 | }
|
---|
231 | else {
|
---|
232 | index--;
|
---|
233 | }
|
---|
234 | }
|
---|
235 | name = null;
|
---|
236 | plugin = null;
|
---|
237 | }
|
---|
238 | }
|
---|
239 | Element element = CollectionDesignManager.collect_config.document.createElement(CollectionConfiguration.PLUGIN_ELEMENT);
|
---|
240 | element.setAttribute(CollectionConfiguration.TYPE_ATTRIBUTE, CollectionConfiguration.SEPARATOR_ATTRIBUTE);
|
---|
241 | element.setAttribute(CollectionConfiguration.SEPARATOR_ATTRIBUTE, CollectionConfiguration.TRUE_STR);
|
---|
242 | separator_plugin = new PlugIn(element, null);
|
---|
243 | ///atherer.println("Adding plugin separator at: " + separator_index);
|
---|
244 | add(separator_index, separator_plugin);
|
---|
245 | }
|
---|
246 |
|
---|
247 | /** 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.
|
---|
248 | * @param plugin The <strong>PlugIn</strong> to remove.
|
---|
249 | */
|
---|
250 | public void removePlugIn(PlugIn plugin) {
|
---|
251 | remove(plugin);
|
---|
252 | Gatherer.c_man.configurationChanged();
|
---|
253 | }
|
---|
254 |
|
---|
255 | /** Method to cache the current contents of library (known plugins) to file.
|
---|
256 | */
|
---|
257 | public void savePlugIns() {
|
---|
258 | try {
|
---|
259 | FileOutputStream file = new FileOutputStream(Utility.BASE_DIR + "plugins.dat");
|
---|
260 | ObjectOutputStream out = new ObjectOutputStream(file);
|
---|
261 | out.writeObject(library);
|
---|
262 | out.close();
|
---|
263 | }
|
---|
264 | catch (Exception error) {
|
---|
265 | Gatherer.printStackTrace(error);
|
---|
266 | }
|
---|
267 | }
|
---|
268 |
|
---|
269 | /** Determine the current separator index. */
|
---|
270 | private int findSeparatorIndex() {
|
---|
271 | int separator_index = getSize() - 1;
|
---|
272 | while(separator_index >= 0) {
|
---|
273 | PlugIn search = (PlugIn) getElementAt(separator_index);
|
---|
274 | if(search.isSeparator()) {
|
---|
275 | return separator_index;
|
---|
276 | }
|
---|
277 | separator_index--;
|
---|
278 | }
|
---|
279 | return separator_index;
|
---|
280 | }
|
---|
281 |
|
---|
282 |
|
---|
283 | /** Retrieve a list of those plugins that are in library but not in the assigned plugins. */
|
---|
284 | private Object[] getAvailable() {
|
---|
285 | ArrayList available = new ArrayList();
|
---|
286 | int library_size = library.size();
|
---|
287 | for(int i = 0; i < library_size; i++) {
|
---|
288 | PlugIn plugin = (PlugIn) library.get(i);
|
---|
289 | if(!plugin.isAbstract()) {
|
---|
290 | available.add(plugin);
|
---|
291 | }
|
---|
292 | plugin = null;
|
---|
293 | }
|
---|
294 | // Now go through the assigned plugins, and remove any that match.
|
---|
295 | available.removeAll(children());
|
---|
296 | //Gatherer.println("There are a total of " + library.size() + " plugins in the library.");
|
---|
297 | //Gatherer.println("However " + children().size() + " are in use,");
|
---|
298 | //Gatherer.println("So only " + available.size() + " remain.");
|
---|
299 | return available.toArray();
|
---|
300 | }
|
---|
301 |
|
---|
302 | /** Method to extract just the plugins name from a file object.
|
---|
303 | * @param plugin The <strong>File</strong> which references a certain plugin.
|
---|
304 | * @return A <strong>String</strong> containing just the plugins name, without extension.
|
---|
305 | */
|
---|
306 | private String getPlugInName(File plugin) {
|
---|
307 | String name = plugin.getName();
|
---|
308 | if(name.indexOf(".") != -1) {
|
---|
309 | name = name.substring(0, name.indexOf("."));
|
---|
310 | }
|
---|
311 | return name;
|
---|
312 | }
|
---|
313 |
|
---|
314 | /** Method to load the details of a single plug-in.
|
---|
315 | * @param plugin The plugin <strong>File</strong> you wish to load.
|
---|
316 | */
|
---|
317 | private void loadPlugIn(File plugin) {
|
---|
318 | Document document = null;
|
---|
319 | // Run pluginfo on this plugin, and then send the results for parsing.
|
---|
320 | try {
|
---|
321 | String args[] = null;
|
---|
322 | if(Utility.isWindows()) {
|
---|
323 | args = new String[4];
|
---|
324 | if(Gatherer.config.perl_path != null) {
|
---|
325 | args[0] = Gatherer.config.perl_path;
|
---|
326 | }
|
---|
327 | else {
|
---|
328 | args[0] = "Perl.exe";
|
---|
329 | }
|
---|
330 | args[1] = Gatherer.config.gsdl_path + "bin" + File.separator + "script" + File.separator + "pluginfo.pl";
|
---|
331 | args[2] = "-xml";
|
---|
332 | args[3] = getPlugInName(plugin);
|
---|
333 | }
|
---|
334 | else {
|
---|
335 | args = new String[3];
|
---|
336 | args[0] = "pluginfo.pl";
|
---|
337 | args[1] = "-xml";
|
---|
338 | args[2] = getPlugInName(plugin);
|
---|
339 | }
|
---|
340 | // Create the process.
|
---|
341 | Runtime runtime = Runtime.getRuntime();
|
---|
342 | Process process = runtime.exec(args);
|
---|
343 | //InputStream input_stream = process.getErrorStream();
|
---|
344 | BufferedReader error_in = new BufferedReader(new InputStreamReader(process.getErrorStream()));
|
---|
345 | String line = "";
|
---|
346 | StringBuffer xml = new StringBuffer("");
|
---|
347 | boolean xml_content = false;
|
---|
348 | while((line = error_in.readLine()) != null) {
|
---|
349 | if(xml_content) {
|
---|
350 | xml.append(line);
|
---|
351 | xml.append("\n");
|
---|
352 | }
|
---|
353 | else if(line.trim().startsWith("<?xml")) {
|
---|
354 | xml_content = true;
|
---|
355 | xml.append(line);
|
---|
356 | xml.append("\n");
|
---|
357 | }
|
---|
358 | }
|
---|
359 | error_in = null;
|
---|
360 | process = null;
|
---|
361 | runtime = null;
|
---|
362 | args = null;
|
---|
363 | // If something has gone horribly wrong then xml will be empty.
|
---|
364 | if(xml.length() != 0) {
|
---|
365 | // Then read the xml from the piped input stream.
|
---|
366 | InputSource source = new InputSource(new StringReader(xml.toString()));
|
---|
367 | DOMParser parser = new DOMParser();
|
---|
368 | parser.parse(source);
|
---|
369 | document = parser.getDocument();
|
---|
370 | parser = null;
|
---|
371 | source = null;
|
---|
372 | }
|
---|
373 | else {
|
---|
374 | String plugin_name = getPlugInName(plugin);
|
---|
375 | //Gatherer.println("Zero length argument xml detected for: " + plugin_name);
|
---|
376 | String[] margs = new String[1];
|
---|
377 | margs[0] = plugin_name;
|
---|
378 | JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CDM.PlugInManager.PlugIn_XML_Parse_Failed", margs), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
|
---|
379 | }
|
---|
380 | }
|
---|
381 | catch (Exception error) {
|
---|
382 | System.err.println("Failed when trying to parse: " + plugin.getName());
|
---|
383 | error.printStackTrace();
|
---|
384 | }
|
---|
385 | if(document != null) {
|
---|
386 | parseXML(document.getDocumentElement());
|
---|
387 | }
|
---|
388 | }
|
---|
389 |
|
---|
390 | /** Method to initially load information from the standard plug-ins within the gsdl Perl library.
|
---|
391 | */
|
---|
392 | private void loadPlugIns() {
|
---|
393 | // Attempt to restore the cached file.
|
---|
394 | try {
|
---|
395 | FileInputStream file = new FileInputStream(Utility.BASE_DIR + "plugins.dat");
|
---|
396 | ObjectInputStream input = new ObjectInputStream(file);
|
---|
397 | library = (ArrayList) input.readObject();
|
---|
398 | }
|
---|
399 | catch (Exception error) {
|
---|
400 | }
|
---|
401 | if(library == null) {
|
---|
402 | library = new ArrayList();
|
---|
403 | // Retrieve the gsdl home directory...
|
---|
404 | String directory = Gatherer.config.gsdl_path;
|
---|
405 | directory = directory + "perllib" + File.separator + "plugins" + File.separator;
|
---|
406 | loadPlugIns(new File(directory));
|
---|
407 | }
|
---|
408 | }
|
---|
409 | /** Method to load plug-in information from a specified directory. Of course no plug-ins may be found at this location.
|
---|
410 | * @param directory A <strong>File</strong> indicating the directory to be scanned for plug-ins.
|
---|
411 | */
|
---|
412 | private void loadPlugIns(File directory) {
|
---|
413 | File files[] = directory.listFiles();
|
---|
414 | if(files != null) {
|
---|
415 | // Create a progress indicator.
|
---|
416 | ParsingProgress progress = new ParsingProgress(Dictionary.get("CDM.PlugInManager.Parsing.Title"), Dictionary.get("CDM.PlugInManager.Parsing.Message"), files.length);
|
---|
417 | for(int i = 0; i < files.length; i++) {
|
---|
418 | // We only want to check Perl Modules.
|
---|
419 | if(files[i].getName().endsWith(".pm")) {
|
---|
420 | loadPlugIn(files[i]);
|
---|
421 | }
|
---|
422 | progress.inc();
|
---|
423 | }
|
---|
424 | progress.dispose();
|
---|
425 | }
|
---|
426 | }
|
---|
427 |
|
---|
428 | private PlugIn parseXML(Node root) {
|
---|
429 | PlugIn plugin = new PlugIn();
|
---|
430 | String node_name = null;
|
---|
431 | for(Node node = root.getFirstChild(); node != null;
|
---|
432 | node = node.getNextSibling()) {
|
---|
433 | node_name = node.getNodeName();
|
---|
434 | if(node_name.equalsIgnoreCase("Name")) {
|
---|
435 | String name = MSMUtils.getValue(node);
|
---|
436 | // 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.
|
---|
437 | PlugIn existing = getBasePlugIn(name);
|
---|
438 | if(existing != null) {
|
---|
439 | return existing;
|
---|
440 | }
|
---|
441 | plugin.setName(name);
|
---|
442 | }
|
---|
443 | else if(node_name.equalsIgnoreCase("Desc")) {
|
---|
444 | plugin.setDescription(MSMUtils.getValue(node));
|
---|
445 | }
|
---|
446 | else if(node_name.equalsIgnoreCase(CollectionConfiguration.ABSTRACT_ELEMENT)) {
|
---|
447 | System.err.println("Is " + plugin.getName() + " abstract? " + MSMUtils.getValue(node).equalsIgnoreCase(CollectionConfiguration.YES_STR));
|
---|
448 | plugin.setIsAbstract(MSMUtils.getValue(node).equalsIgnoreCase(CollectionConfiguration.YES_STR));
|
---|
449 | }
|
---|
450 | // Parse the multitude of arguments.
|
---|
451 | else if(node_name.equalsIgnoreCase("Arguments")) {
|
---|
452 | for(Node arg = node.getFirstChild(); arg != null; arg = arg.getNextSibling()) {
|
---|
453 | node_name = arg.getNodeName();
|
---|
454 | // An option.
|
---|
455 | if(node_name.equalsIgnoreCase("Option")) {
|
---|
456 | Argument argument = new Argument();
|
---|
457 | // If its an option we parse the multitude of details an options might have.
|
---|
458 | for(Node det = arg.getFirstChild(); det != null; det = det.getNextSibling()) {
|
---|
459 | node_name = det.getNodeName();
|
---|
460 | if(node_name.equalsIgnoreCase("Name")) {
|
---|
461 | argument.setName(MSMUtils.getValue(det));
|
---|
462 | }
|
---|
463 | else if(node_name.equalsIgnoreCase("Desc")) {
|
---|
464 | argument.setDescription(MSMUtils.getValue(det));
|
---|
465 | }
|
---|
466 | else if(node_name.equalsIgnoreCase("Type")) {
|
---|
467 | argument.setType(MSMUtils.getValue(det));
|
---|
468 | }
|
---|
469 | else if(node_name.equalsIgnoreCase("Default")) {
|
---|
470 | argument.setDefaultValue(MSMUtils.getValue(det));
|
---|
471 | }
|
---|
472 | else if(node_name.equalsIgnoreCase("List")) {
|
---|
473 | // Two final loops are required to parse lists.
|
---|
474 | for(Node value = det.getFirstChild(); value != null; value = value.getNextSibling()) {
|
---|
475 | if(value.getNodeName().equalsIgnoreCase("Value")) {
|
---|
476 | String key = null;
|
---|
477 | String desc = "";
|
---|
478 | for(Node subvalue = value.getFirstChild(); subvalue != null; subvalue = subvalue.getNextSibling()) {
|
---|
479 | node_name = subvalue.getNodeName();
|
---|
480 | if(node_name.equalsIgnoreCase("Name")) {
|
---|
481 | key = MSMUtils.getValue(subvalue);
|
---|
482 | }
|
---|
483 | else if(node_name.equalsIgnoreCase("Desc")) {
|
---|
484 | desc = MSMUtils.getValue(subvalue);
|
---|
485 | }
|
---|
486 | }
|
---|
487 | if(key != null) {
|
---|
488 | argument.addOption(key, desc);
|
---|
489 | }
|
---|
490 | }
|
---|
491 | }
|
---|
492 | }
|
---|
493 | else if(node_name.equalsIgnoreCase("Required")) {
|
---|
494 | String v = MSMUtils.getValue(det);
|
---|
495 | if(v != null && v.equalsIgnoreCase("yes")) {
|
---|
496 | argument.setRequired(true);
|
---|
497 | }
|
---|
498 | }
|
---|
499 | }
|
---|
500 | plugin.addArgument(argument);
|
---|
501 | }
|
---|
502 | // A super plugin class.
|
---|
503 | else if(node_name.equalsIgnoreCase("PlugInfo")) {
|
---|
504 | PlugIn super_plugin = parseXML(arg);
|
---|
505 | plugin.setSuper(super_plugin);
|
---|
506 | }
|
---|
507 | }
|
---|
508 | }
|
---|
509 | }
|
---|
510 | if(plugin.getName() != null) {
|
---|
511 | addPlugIn(plugin);
|
---|
512 | return plugin;
|
---|
513 | }
|
---|
514 | return null;
|
---|
515 | }
|
---|
516 |
|
---|
517 | /** A class which provodes controls for assigned and editing plugins. */
|
---|
518 | private class PlugInControl
|
---|
519 | extends JPanel
|
---|
520 | implements Control {
|
---|
521 | /** Button for adding plugins. */
|
---|
522 | private JButton add = null;
|
---|
523 | /** Button for configuring the selected plugin. */
|
---|
524 | private JButton configure = null;
|
---|
525 | /** Buttom to move an assinged plugin as low in the order as possible. */
|
---|
526 | private JButton move_bottom_button = null;
|
---|
527 | /** Button to move an assigned plugin one position lower in the order. */
|
---|
528 | private JButton move_down_button = null;
|
---|
529 | /** Button to move an assigned plugin as high in the order as possible. */
|
---|
530 | private JButton move_top_button = null;
|
---|
531 | /** Button to move an assigned plugin one position higher in the order. */
|
---|
532 | private JButton move_up_button = null;
|
---|
533 | /** Button to remove the selected plugin. */
|
---|
534 | private JButton remove = null;
|
---|
535 | /** A combobox containing all of the known plugins, including those that may have already been assigned. */
|
---|
536 | private GComboBox plugin = null;
|
---|
537 | /** The label next to the plugin combobox. */
|
---|
538 | private JLabel plugin_label = null;
|
---|
539 | /** The label above the assigned plugin list. */
|
---|
540 | private JLabel plugin_list_label = null;
|
---|
541 | /** The title of this view. */
|
---|
542 | private JLabel title = null;
|
---|
543 | /** A list of assigned plugins. */
|
---|
544 | private JList plugin_list = null;
|
---|
545 | /** The area where the add, configure and remove buttons are placed. */
|
---|
546 | private JPanel button_pane = null;
|
---|
547 | /** The region which divides the central portion of the view into list and controls */
|
---|
548 | private JPanel central_pane = null;
|
---|
549 | /** The area where title label and instructions sit. */
|
---|
550 | private JPanel header_pane = null;
|
---|
551 | /** The area where movement buttons are placed. */
|
---|
552 | private JPanel movement_pane = null;
|
---|
553 | /** The small region containing the plugin combobox and its label. */
|
---|
554 | private JPanel plugin_pane = null;
|
---|
555 | /** The pane containing the assigned plugin list and its label. */
|
---|
556 | private JPanel plugin_list_pane = null;
|
---|
557 | /** The text area containing instructions on the use of this control. */
|
---|
558 | private JTextArea instructions = null;
|
---|
559 |
|
---|
560 | /** Constructor.
|
---|
561 | */
|
---|
562 | public PlugInControl() {
|
---|
563 | // Create
|
---|
564 | add = new JButton();
|
---|
565 | add.setMnemonic(KeyEvent.VK_A);
|
---|
566 | Dictionary.registerBoth(add, "CDM.PlugInManager.Add", "CDM.PlugInManager.Add_Tooltip");
|
---|
567 |
|
---|
568 | button_pane = new JPanel();
|
---|
569 | central_pane = new JPanel();
|
---|
570 |
|
---|
571 | configure = new JButton();
|
---|
572 | configure.setEnabled(false);
|
---|
573 | configure.setMnemonic(KeyEvent.VK_C);
|
---|
574 | Dictionary.registerBoth(configure, "CDM.PlugInManager.Configure", "CDM.PlugInManager.Configure_Tooltip");
|
---|
575 |
|
---|
576 | header_pane = new JPanel();
|
---|
577 |
|
---|
578 | instructions = new JTextArea();
|
---|
579 | instructions.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
|
---|
580 | instructions.setEditable(false);
|
---|
581 | instructions.setLineWrap(true);
|
---|
582 | instructions.setRows(6);
|
---|
583 | instructions.setWrapStyleWord(true);
|
---|
584 | Dictionary.registerText(instructions, "CDM.PlugInManager.Instructions");
|
---|
585 |
|
---|
586 | move_top_button = new DoubleImageButton("", Utility.getImage("arrow-top.gif"), Utility.getImage("arrow-top-disabled.gif"));
|
---|
587 | move_top_button.setEnabled(false);
|
---|
588 | move_top_button.setMnemonic(KeyEvent.VK_T);
|
---|
589 | // move_top_button.setDisplayedMnemonicIndex(8); // !! English-centric hack
|
---|
590 | move_top_button.setPreferredSize(Utility.DOUBLE_IMAGE_BUTTON_SIZE);
|
---|
591 | Dictionary.registerBoth(move_top_button, "CDM.Move.Move_Top", "CDM.Move.Move_Top_Tooltip");
|
---|
592 |
|
---|
593 | move_up_button = new DoubleImageButton("", Utility.getImage("arrow-up.gif"), Utility.getImage("arrow-up-disabled.gif"));
|
---|
594 | move_up_button.setEnabled(false);
|
---|
595 | move_up_button.setMnemonic(KeyEvent.VK_U);
|
---|
596 | move_up_button.setPreferredSize(Utility.DOUBLE_IMAGE_BUTTON_SIZE);
|
---|
597 | Dictionary.registerBoth(move_up_button, "CDM.Move.Move_Up", "CDM.Move.Move_Up_Tooltip");
|
---|
598 |
|
---|
599 | move_down_button = new DoubleImageButton("", Utility.getImage("arrow-down.gif"), Utility.getImage("arrow-down-disabled.gif"));
|
---|
600 | move_down_button.setEnabled(false);
|
---|
601 | move_down_button.setMnemonic(KeyEvent.VK_D);
|
---|
602 | move_down_button.setPreferredSize(Utility.DOUBLE_IMAGE_BUTTON_SIZE);
|
---|
603 | Dictionary.registerBoth(move_down_button, "CDM.Move.Move_Down", "CDM.Move.Move_Down_Tooltip");
|
---|
604 |
|
---|
605 | move_bottom_button = new DoubleImageButton("", Utility.getImage("arrow-bottom.gif"), Utility.getImage("arrow-bottom-disabled.gif"));
|
---|
606 | move_bottom_button.setEnabled(false);
|
---|
607 | move_bottom_button.setMnemonic(KeyEvent.VK_B);
|
---|
608 | move_bottom_button.setPreferredSize(Utility.DOUBLE_IMAGE_BUTTON_SIZE);
|
---|
609 | Dictionary.registerBoth(move_bottom_button, "CDM.Move.Move_Bottom", "CDM.Move.Move_Bottom_Tooltip");
|
---|
610 |
|
---|
611 | movement_pane = new JPanel();
|
---|
612 |
|
---|
613 | PlugInComboboxListener picl = new PlugInComboboxListener();
|
---|
614 | plugin = new GComboBox(getAvailable());
|
---|
615 | plugin.setBackgroundNonSelectionColor(Gatherer.config.getColor("coloring.editable_background", false));
|
---|
616 | plugin.setBackgroundSelectionColor(Gatherer.config.getColor("coloring.collection_selection_background", false));
|
---|
617 | plugin.setEditable(true);
|
---|
618 | plugin.setTextNonSelectionColor(Gatherer.config.getColor("coloring.workspace_tree_foreground", false));
|
---|
619 | plugin.setTextSelectionColor(Gatherer.config.getColor("coloring.collection_selection_foreground", false));
|
---|
620 | picl.itemStateChanged(new ItemEvent(plugin, 0, null, ItemEvent.SELECTED));
|
---|
621 |
|
---|
622 | plugin_label = new JLabel();
|
---|
623 | Dictionary.registerText(plugin_label, "CDM.PlugInManager.PlugIn");
|
---|
624 |
|
---|
625 | plugin_list = new JList(model);
|
---|
626 | plugin_list.setCellRenderer(new ListRenderer());
|
---|
627 | plugin_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
---|
628 | plugin_list_label = new JLabel();
|
---|
629 | plugin_list_label.setHorizontalAlignment(JLabel.CENTER);
|
---|
630 | plugin_list_label.setOpaque(true);
|
---|
631 | Dictionary.registerText(plugin_list_label, "CDM.PlugInManager.Assigned");
|
---|
632 |
|
---|
633 | plugin_list_pane = new JPanel();
|
---|
634 | plugin_pane = new JPanel();
|
---|
635 |
|
---|
636 | remove = new JButton();
|
---|
637 | remove.setEnabled(false);
|
---|
638 | remove.setMnemonic(KeyEvent.VK_R);
|
---|
639 | Dictionary.registerBoth(remove, "CDM.PlugInManager.Remove", "CDM.PlugInManager.Remove_Tooltip");
|
---|
640 |
|
---|
641 | title = new JLabel();
|
---|
642 | title.setHorizontalAlignment(JLabel.CENTER);
|
---|
643 | title.setOpaque(true);
|
---|
644 | Dictionary.registerText(title, "CDM.PlugInManager.Title");
|
---|
645 |
|
---|
646 | // Listeners
|
---|
647 | add.addActionListener(new AddListener());
|
---|
648 | configure.addActionListener(new ConfigureListener());
|
---|
649 | MoveListener ml = new MoveListener();
|
---|
650 | move_bottom_button.addActionListener(ml);
|
---|
651 | move_down_button.addActionListener(ml);
|
---|
652 | move_top_button.addActionListener(ml);
|
---|
653 | move_up_button.addActionListener(ml);
|
---|
654 | plugin.addItemListener(picl);
|
---|
655 | remove.addActionListener(new RemoveListener());
|
---|
656 | plugin_list.addMouseListener(new ClickListener());
|
---|
657 | plugin_list.addListSelectionListener(new ListListener());
|
---|
658 | picl = null;
|
---|
659 |
|
---|
660 | // Layout
|
---|
661 | title.setBorder(BorderFactory.createEmptyBorder(0,0,2,0));
|
---|
662 |
|
---|
663 | instructions.setBorder(BorderFactory.createEmptyBorder(2,5,2,5));
|
---|
664 |
|
---|
665 | header_pane.setLayout(new BorderLayout());
|
---|
666 | header_pane.add(title, BorderLayout.NORTH);
|
---|
667 | header_pane.add(new JScrollPane(instructions), BorderLayout.CENTER);
|
---|
668 |
|
---|
669 | plugin_list_label.setBorder(BorderFactory.createEmptyBorder(0,2,0,2));
|
---|
670 |
|
---|
671 | movement_pane.setBorder(BorderFactory.createEmptyBorder(0,2,0,0));
|
---|
672 | movement_pane.setLayout(new GridLayout(4,1));
|
---|
673 | movement_pane.add(move_top_button);
|
---|
674 | movement_pane.add(move_up_button);
|
---|
675 | movement_pane.add(move_down_button);
|
---|
676 | movement_pane.add(move_bottom_button);
|
---|
677 |
|
---|
678 | plugin_list_pane.setLayout(new BorderLayout());
|
---|
679 | plugin_list_pane.add(plugin_list_label, BorderLayout.NORTH);
|
---|
680 | plugin_list_pane.add(new JScrollPane(plugin_list), BorderLayout.CENTER);
|
---|
681 | plugin_list_pane.add(movement_pane, BorderLayout.EAST);
|
---|
682 |
|
---|
683 | plugin_label.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
|
---|
684 |
|
---|
685 | plugin_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,0));
|
---|
686 | plugin_pane.setLayout(new GridLayout(1,2));
|
---|
687 | plugin_pane.add(plugin_label);
|
---|
688 | plugin_pane.add(plugin);
|
---|
689 |
|
---|
690 | button_pane.setLayout(new GridLayout(1,3));
|
---|
691 | button_pane.add(add);
|
---|
692 | button_pane.add(configure);
|
---|
693 | button_pane.add(remove);
|
---|
694 |
|
---|
695 | // Scope these mad bordering skillz.
|
---|
696 | // !! TO DO: Dictionary registration !!
|
---|
697 | JPanel temp = new JPanel(new BorderLayout());
|
---|
698 | temp.setBorder
|
---|
699 | (BorderFactory.createCompoundBorder
|
---|
700 | (BorderFactory.createEmptyBorder(5,0,5,0),
|
---|
701 | BorderFactory.createCompoundBorder
|
---|
702 | (BorderFactory.createTitledBorder(Dictionary.get("CDM.PlugInManager.Controls")),
|
---|
703 | BorderFactory.createEmptyBorder(2,2,2,2))));
|
---|
704 |
|
---|
705 | temp.add(plugin_pane, BorderLayout.NORTH);
|
---|
706 | temp.add(button_pane, BorderLayout.SOUTH);
|
---|
707 |
|
---|
708 | central_pane.setLayout(new BorderLayout());
|
---|
709 | central_pane.add(plugin_list_pane, BorderLayout.CENTER);
|
---|
710 | central_pane.add(temp, BorderLayout.SOUTH);
|
---|
711 |
|
---|
712 | setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
|
---|
713 | setLayout(new BorderLayout());
|
---|
714 | add(header_pane, BorderLayout.NORTH);
|
---|
715 | add(central_pane, BorderLayout.CENTER);
|
---|
716 | }
|
---|
717 |
|
---|
718 | /** Method which acts like a destructor, tidying up references to persistant objects.
|
---|
719 | */
|
---|
720 | public void destroy() {
|
---|
721 | }
|
---|
722 |
|
---|
723 | /** This method is overridden to ensure the instructions are scrolled to top, before the super classes updateUI() is called.
|
---|
724 | */
|
---|
725 | public void gainFocus() {
|
---|
726 | if(instructions != null) {
|
---|
727 | instructions.setCaretPosition(0);
|
---|
728 | }
|
---|
729 | super.updateUI();
|
---|
730 | }
|
---|
731 |
|
---|
732 | public void loseFocus() {
|
---|
733 | }
|
---|
734 |
|
---|
735 | /** This class listens for actions upon the add button in the controls, and if detected calls the <i>assignPlugIn()</i> method. */
|
---|
736 | private class AddListener
|
---|
737 | implements ActionListener {
|
---|
738 | /** 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.
|
---|
739 | * @param event An <strong>ActionEvent</strong> containing information garnered from the control action.
|
---|
740 | */
|
---|
741 | public void actionPerformed(ActionEvent event) {
|
---|
742 | Object selected_object = plugin.getSelectedItem();
|
---|
743 | if(selected_object != null) {
|
---|
744 | // Retrieve the base plugin if any
|
---|
745 | PlugIn base_plugin = getBasePlugIn(selected_object.toString());
|
---|
746 |
|
---|
747 | // Create a new element in the DOM
|
---|
748 | Element element = CollectionDesignManager.collect_config.document.createElement(CollectionConfiguration.PLUGIN_ELEMENT);
|
---|
749 | // Remember that the plugin supplied might be a custom string rather than a base plugin
|
---|
750 | PlugIn new_plugin = null;
|
---|
751 | if(base_plugin != null) {
|
---|
752 | //Gatherer.println("New PlugIn based on existing PlugIn");
|
---|
753 | element.setAttribute(CollectionConfiguration.TYPE_ATTRIBUTE, base_plugin.getName());
|
---|
754 | new_plugin = new PlugIn(element, base_plugin);
|
---|
755 | }
|
---|
756 | else {
|
---|
757 | //Gatherer.println("New Custom PlugIn");
|
---|
758 | element.setAttribute(CollectionConfiguration.TYPE_ATTRIBUTE, selected_object.toString());
|
---|
759 | new_plugin = new PlugIn(element, null);
|
---|
760 | }
|
---|
761 | if(!model.contains(new_plugin) || new_plugin.getName().equals(StaticStrings.UNKNOWNPLUG_STR)) {
|
---|
762 | // Automatically chain to configuration. This ensures required arguments are filled out.
|
---|
763 | ArgumentConfiguration ac = new ArgumentConfiguration(new_plugin);
|
---|
764 | if(ac.display()) {
|
---|
765 | assignPlugIn(new_plugin);
|
---|
766 | plugin_list.setSelectedValue(new_plugin, true);
|
---|
767 | // Since we weren't cancelled, and if there was a base plugin, ensure it no longer is shown as available, unless it is the UnknownPlugIn which can be added several times
|
---|
768 | if(base_plugin != null && !base_plugin.getName().equals(StaticStrings.UNKNOWNPLUG_STR)) {
|
---|
769 | plugin.removeItem(base_plugin);
|
---|
770 | }
|
---|
771 | }
|
---|
772 | ac = null;
|
---|
773 | new_plugin = null;
|
---|
774 | plugin.setSelectedIndex(0);
|
---|
775 | }
|
---|
776 | else {
|
---|
777 | JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CDM.PlugInManager.PlugIn_Exists"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
|
---|
778 | }
|
---|
779 | base_plugin = null;
|
---|
780 | }
|
---|
781 | }
|
---|
782 | }
|
---|
783 |
|
---|
784 | /** Listens for double clicks apon the list and react as if the configure button was pushed. */
|
---|
785 | private class ClickListener
|
---|
786 | extends MouseAdapter {
|
---|
787 | /** Called whenever the mouse is clicked over a registered component, we use this to chain through to the configure prompt.
|
---|
788 | * @param event A <strong>MouseEvent</strong> containing information about the mouse click.
|
---|
789 | */
|
---|
790 | public void mouseClicked(MouseEvent event) {
|
---|
791 | if(event.getClickCount() == 2 ) {
|
---|
792 | if(!plugin_list.isSelectionEmpty()) {
|
---|
793 | PlugIn plugin = (PlugIn) plugin_list.getSelectedValue();
|
---|
794 | if(!plugin.isSeparator()) {
|
---|
795 | ArgumentConfiguration ac = new ArgumentConfiguration(plugin);
|
---|
796 | if(ac.display()) {
|
---|
797 | refresh(plugin);
|
---|
798 | }
|
---|
799 | ac.destroy();
|
---|
800 | ac = null;
|
---|
801 | }
|
---|
802 | }
|
---|
803 | }
|
---|
804 | }
|
---|
805 | }
|
---|
806 |
|
---|
807 | /** 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.
|
---|
808 | * @see org.greenstone.gatherer.cdm.ArgumentConfiguration
|
---|
809 | */
|
---|
810 | private class ConfigureListener
|
---|
811 | implements ActionListener {
|
---|
812 | /** 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.
|
---|
813 | * @param event An <strong>ActionEvent</strong> containing information garnered from the control action.
|
---|
814 | */
|
---|
815 | public void actionPerformed(ActionEvent event) {
|
---|
816 | if(!plugin_list.isSelectionEmpty()) {
|
---|
817 | PlugIn plugin = (PlugIn) plugin_list.getSelectedValue();
|
---|
818 | if(!plugin.isSeparator()) {
|
---|
819 | ArgumentConfiguration ac = new ArgumentConfiguration(plugin);
|
---|
820 | if(ac.display()) {
|
---|
821 | refresh(plugin);
|
---|
822 | }
|
---|
823 | ac.destroy();
|
---|
824 | ac = null;
|
---|
825 | }
|
---|
826 | }
|
---|
827 | }
|
---|
828 | }
|
---|
829 |
|
---|
830 | /** 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 */
|
---|
831 | private class ListListener
|
---|
832 | implements ListSelectionListener {
|
---|
833 |
|
---|
834 | public void valueChanged(ListSelectionEvent e) {
|
---|
835 | if (!e.getValueIsAdjusting()) { // we get two events for one change in list selection - use the false one (the second one)
|
---|
836 | if (plugin_list.isSelectionEmpty()) {
|
---|
837 | move_top_button.setEnabled(false);
|
---|
838 | move_up_button.setEnabled(false);
|
---|
839 | move_down_button.setEnabled(false);
|
---|
840 | move_bottom_button.setEnabled(false);
|
---|
841 | configure.setEnabled(false);
|
---|
842 | remove.setEnabled(false);
|
---|
843 | }
|
---|
844 | else {
|
---|
845 | configure.setEnabled(true);
|
---|
846 | // Some buttons are only available for plugins other than ArcPlug and RecPlug
|
---|
847 | PlugIn selected_plugin = (PlugIn) plugin_list.getSelectedValue();
|
---|
848 | String plugin_name = selected_plugin.getName();
|
---|
849 | if(plugin_name.equals(StaticStrings.ARCPLUG_STR) || plugin_name.equals(StaticStrings.RECPLUG_STR)) {
|
---|
850 | move_top_button.setEnabled(false);
|
---|
851 | move_up_button.setEnabled(false);
|
---|
852 | move_down_button.setEnabled(false);
|
---|
853 | move_bottom_button.setEnabled(false);
|
---|
854 | remove.setEnabled(false);
|
---|
855 | }
|
---|
856 | else {
|
---|
857 | // Move ups are only enabled if the selected plugin isn't already at the top
|
---|
858 | PlugIn first_plugin = (PlugIn) getElementAt(0);
|
---|
859 | if(!first_plugin.equals(selected_plugin)) {
|
---|
860 | move_top_button.setEnabled(true);
|
---|
861 | move_up_button.setEnabled(true);
|
---|
862 | }
|
---|
863 | else {
|
---|
864 | move_top_button.setEnabled(false);
|
---|
865 | move_up_button.setEnabled(false);
|
---|
866 | }
|
---|
867 | // And move downs are only allowed when the selected plugin isn't at an index one less than the separator line.
|
---|
868 | int separator_index = findSeparatorIndex();
|
---|
869 | int selected_index = plugin_list.getSelectedIndex();
|
---|
870 | if(selected_index != separator_index - 1) {
|
---|
871 | move_down_button.setEnabled(true);
|
---|
872 | move_bottom_button.setEnabled(true);
|
---|
873 | }
|
---|
874 | else {
|
---|
875 | move_down_button.setEnabled(false);
|
---|
876 | move_bottom_button.setEnabled(false);
|
---|
877 | }
|
---|
878 | remove.setEnabled(true);
|
---|
879 | }
|
---|
880 | selected_plugin = null;
|
---|
881 | plugin_name = null;
|
---|
882 | }
|
---|
883 | }
|
---|
884 | }
|
---|
885 | }
|
---|
886 |
|
---|
887 | /** A special list renderer which is able to render separating lines as well. */
|
---|
888 | private class ListRenderer
|
---|
889 | extends DefaultListCellRenderer {
|
---|
890 | /** 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.
|
---|
891 | * @param list - The <strong>JList</strong> we're painting.
|
---|
892 | * @param value - The value returned by list.getModel().getElementAt(index) as an <strong>Object</strong>.
|
---|
893 | * @param index - The cells index as an <i>int</i>.
|
---|
894 | * @param isSelected - <i>true</i> if the specified cell was selected.
|
---|
895 | * @param cellHasFocus - <i>true</i> if the specified cell has the focus.
|
---|
896 | * @return A <strong>Component</strong> whose paint() method will render the specified value.
|
---|
897 | * @see javax.swing.JList
|
---|
898 | * @see javax.swing.JSeparator
|
---|
899 | * @see javax.swing.ListModel
|
---|
900 | * @see javax.swing.ListSelectionModel
|
---|
901 | */
|
---|
902 | public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
|
---|
903 | PlugIn plugin = (PlugIn) value;
|
---|
904 | if(plugin.isSeparator()) {
|
---|
905 | return separator;
|
---|
906 | }
|
---|
907 | else {
|
---|
908 | return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
---|
909 | }
|
---|
910 | }
|
---|
911 | }
|
---|
912 |
|
---|
913 |
|
---|
914 | /** 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. */
|
---|
915 | private class MoveListener
|
---|
916 | implements ActionListener {
|
---|
917 | /** 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.
|
---|
918 | * @param event An <strong>ActionEvent</strong> containing information garnered from the control action.
|
---|
919 | */
|
---|
920 | public void actionPerformed(ActionEvent event) {
|
---|
921 | if (!plugin_list.isSelectionEmpty()) {
|
---|
922 | Object object = plugin_list.getSelectedValue();
|
---|
923 | if (object instanceof PlugIn) {
|
---|
924 | PlugIn plugin = (PlugIn) object;
|
---|
925 | if (event.getSource() == move_top_button) {
|
---|
926 | movePlugIn(plugin, true, true);
|
---|
927 | }
|
---|
928 | else if (event.getSource() == move_up_button) {
|
---|
929 | movePlugIn(plugin, true, false);
|
---|
930 | }
|
---|
931 | else if (event.getSource() == move_down_button) {
|
---|
932 | movePlugIn(plugin, false, false);
|
---|
933 | }
|
---|
934 | else if (event.getSource() == move_bottom_button) {
|
---|
935 | movePlugIn(plugin, false, true);
|
---|
936 | }
|
---|
937 | plugin_list.setSelectedValue(plugin, true);
|
---|
938 | }
|
---|
939 | }
|
---|
940 | }
|
---|
941 | }
|
---|
942 |
|
---|
943 | /** This listener reacts to changes in the current selection of the plugin combobox. */
|
---|
944 | private class PlugInComboboxListener
|
---|
945 | implements ItemListener {
|
---|
946 | /** When a user selects a certain plugin, update the tooltip to show the plugin description. */
|
---|
947 | public void itemStateChanged(ItemEvent event) {
|
---|
948 | if(event.getStateChange() == ItemEvent.SELECTED) {
|
---|
949 | // Retrieve the selected plugin
|
---|
950 | Object current_selection = plugin.getSelectedItem();
|
---|
951 | // And reset the tooltip. If the plugin is null or is a string, then go back to the default message
|
---|
952 | if(current_selection == null || current_selection instanceof String) {
|
---|
953 | Dictionary.registerTooltip(plugin, "CDM.PlugInManager.PlugIn_Tooltip");
|
---|
954 | }
|
---|
955 | else {
|
---|
956 | PlugIn current_plugin = (PlugIn) current_selection;
|
---|
957 | Dictionary.registerTooltip(plugin, Utility.formatHTMLWidth(current_plugin.getDescription(), 40), false);
|
---|
958 | current_plugin = null;
|
---|
959 | }
|
---|
960 | current_selection = null;
|
---|
961 | }
|
---|
962 | }
|
---|
963 | }
|
---|
964 |
|
---|
965 | /** This class listens for actions upon the remove button in the controls, and if detected calls the <i>removePlugIn()</i> method.
|
---|
966 | */
|
---|
967 | private class RemoveListener
|
---|
968 | implements ActionListener {
|
---|
969 | /** 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.
|
---|
970 | * @param event An <strong>ActionEvent</strong> containing information garnered from the control action.
|
---|
971 | */
|
---|
972 | public void actionPerformed(ActionEvent event) {
|
---|
973 | if(!plugin_list.isSelectionEmpty()) {
|
---|
974 | Object [] objects = plugin_list.getSelectedValues();
|
---|
975 | for(int i = 0; i < objects.length; i++) {
|
---|
976 | if(objects[i] instanceof PlugIn) {
|
---|
977 | removePlugIn((PlugIn)objects[i]);
|
---|
978 | }
|
---|
979 | }
|
---|
980 | // Refresh the available plugins
|
---|
981 | plugin.setModel(new DefaultComboBoxModel(getAvailable()));
|
---|
982 | }
|
---|
983 | remove.setEnabled(false);
|
---|
984 | }
|
---|
985 | }
|
---|
986 | }
|
---|
987 | /** Creates a list separator.
|
---|
988 | * Code courtesy of Farwell, Paul. Contact <a href="mailto:[email protected]">[email protected]</a>
|
---|
989 | */
|
---|
990 | static private JPanel getSeparator() {
|
---|
991 | // We put the separator inside a panel to control its appearance
|
---|
992 | JPanel _sepPanel = new JPanel();
|
---|
993 | _sepPanel.setOpaque(false);
|
---|
994 | _sepPanel.setBorder(BorderFactory.createEmptyBorder(1, 3, 1, 3));
|
---|
995 | _sepPanel.setLayout(new BoxLayout(_sepPanel, BoxLayout.Y_AXIS));
|
---|
996 | _sepPanel.add(Box.createRigidArea(new Dimension(0, 4)));
|
---|
997 | _sepPanel.add(new JPopupMenu.Separator());
|
---|
998 | _sepPanel.add(Box.createRigidArea(new Dimension(0, 4)));
|
---|
999 | return _sepPanel;
|
---|
1000 | }
|
---|
1001 | }
|
---|