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.net.*;
|
---|
33 | import java.util.*;
|
---|
34 | import javax.swing.*;
|
---|
35 | import javax.swing.event.*;
|
---|
36 | import javax.swing.plaf.*;
|
---|
37 | import javax.swing.plaf.basic.*;
|
---|
38 | import org.apache.xerces.parsers.*;
|
---|
39 | import org.greenstone.gatherer.Configuration;
|
---|
40 | import org.greenstone.gatherer.DebugStream;
|
---|
41 | import org.greenstone.gatherer.Dictionary;
|
---|
42 | import org.greenstone.gatherer.Gatherer;
|
---|
43 | import org.greenstone.gatherer.collection.CollectionContentsChangedListener;
|
---|
44 | import org.greenstone.gatherer.collection.CollectionManager;
|
---|
45 | import org.greenstone.gatherer.greenstone.Plugins;
|
---|
46 | import org.greenstone.gatherer.gui.DesignPaneHeader;
|
---|
47 | import org.greenstone.gatherer.gui.GComboBox;
|
---|
48 | import org.greenstone.gatherer.gui.GLIButton;
|
---|
49 | import org.greenstone.gatherer.gui.ModalDialog;
|
---|
50 | import org.greenstone.gatherer.gui.WarningDialog;
|
---|
51 | import org.greenstone.gatherer.remote.RemoteGreenstoneServer;
|
---|
52 | import org.greenstone.gatherer.util.JarTools;
|
---|
53 | import org.greenstone.gatherer.util.StaticStrings;
|
---|
54 | import org.greenstone.gatherer.util.Utility;
|
---|
55 | import org.greenstone.gatherer.util.XMLTools;
|
---|
56 | import org.w3c.dom.*;
|
---|
57 | import org.xml.sax.*;
|
---|
58 |
|
---|
59 |
|
---|
60 | /** This class is for maintaining a list of known plug-ins, and importing new plugins using the parser. */
|
---|
61 | public class PluginManager
|
---|
62 | extends DOMProxyListModel
|
---|
63 | implements CollectionContentsChangedListener
|
---|
64 | {
|
---|
65 | /** 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. */
|
---|
66 | private boolean modify_row_count = false;
|
---|
67 | /** The controls for editing the contents of this manager. */
|
---|
68 | private Control controls = null;
|
---|
69 | private DOMProxyListModel model;
|
---|
70 | private JPanel separator;
|
---|
71 | private Plugin separator_plugin;
|
---|
72 |
|
---|
73 | /** The number of plugins that are fixed 'below the line' */
|
---|
74 | private static int NUM_FIXED_PLUGINS = 3;
|
---|
75 | /** Constructor.
|
---|
76 | */
|
---|
77 | public PluginManager() { super(CollectionDesignManager.collect_config.getDocumentElement(), StaticStrings.PLUGIN_ELEMENT, new Plugin());
|
---|
78 | DebugStream.println("PluginManager: " + super.getSize() + " plugins parsed.");
|
---|
79 | model = this;
|
---|
80 |
|
---|
81 | // Force the assigned plugins to be loaded and cached now
|
---|
82 | for (int i = 0; i < getSize(); i++) {
|
---|
83 | getElementAt(i);
|
---|
84 | }
|
---|
85 |
|
---|
86 | // Create the separator, cause we can reuse it.
|
---|
87 | separator = getSeparator();
|
---|
88 | placeSeparator();
|
---|
89 | // check for MetadataXMLPlug
|
---|
90 | ensureMetadataXMLPlugIsLoaded();
|
---|
91 | // Listen for CollectionContentsChanged events, so we can give plugin hints when new files are added
|
---|
92 | CollectionManager.addCollectionContentsChangedListener(this);
|
---|
93 |
|
---|
94 | }
|
---|
95 |
|
---|
96 | private void ensureMetadataXMLPlugIsLoaded() {
|
---|
97 |
|
---|
98 | Plugin metaxmlplug = Plugins.getPlugin(StaticStrings.METADATAXMLPLUG_STR, false);
|
---|
99 | if (metaxmlplug!= null) {
|
---|
100 | if (!contains(metaxmlplug)) {
|
---|
101 | // Create a new element in the DOM
|
---|
102 | Element new_plugin_element = CollectionConfiguration.createElement(StaticStrings.PLUGIN_ELEMENT);
|
---|
103 | new_plugin_element.setAttribute(StaticStrings.TYPE_ATTRIBUTE, metaxmlplug.getName());
|
---|
104 | Plugin new_plugin = new Plugin(new_plugin_element, metaxmlplug);
|
---|
105 | assignPlugin(new_plugin);
|
---|
106 | }
|
---|
107 | }
|
---|
108 | }
|
---|
109 |
|
---|
110 |
|
---|
111 | /** Retrieve a list of the plugins that are available to be added to the collection. */
|
---|
112 | private Object[] getAvailablePlugins()
|
---|
113 | {
|
---|
114 | ArrayList available = new ArrayList();
|
---|
115 |
|
---|
116 | // Add all the non-abstract core Greenstone plugins, except for ArcPlug and RecPlug
|
---|
117 | ArrayList plugins_list = Plugins.getPluginsList();
|
---|
118 | for (int i = 0; i < plugins_list.size(); i++) {
|
---|
119 | Plugin plugin = (Plugin) plugins_list.get(i);
|
---|
120 | if (!plugin.isAbstract()) {
|
---|
121 | String plugin_name = plugin.getName();
|
---|
122 | if (!plugin_name.equals(StaticStrings.ARCPLUG_STR) && !plugin_name.equals(StaticStrings.RECPLUG_STR) && !plugin_name.equals(StaticStrings.METADATAXMLPLUG_STR)) {
|
---|
123 | available.add(plugin);
|
---|
124 | }
|
---|
125 | }
|
---|
126 | }
|
---|
127 |
|
---|
128 | // Sort the available plugins into alphabetical order
|
---|
129 | Collections.sort(available);
|
---|
130 |
|
---|
131 | return available.toArray();
|
---|
132 | }
|
---|
133 |
|
---|
134 |
|
---|
135 | public ArrayList getExploderPlugins(File file)
|
---|
136 | {
|
---|
137 | ArrayList exploder_plugins = new ArrayList();
|
---|
138 | ArrayList plugins_list = Plugins.getPluginsList();
|
---|
139 | for (int i = 0; i < plugins_list.size(); i++) {
|
---|
140 | Plugin plugin = (Plugin) plugins_list.get(i);
|
---|
141 | if (plugin.doesExplodeMetadataDatabases() == true && plugin.doesProcessFile(file)) {
|
---|
142 | exploder_plugins.add(plugin);
|
---|
143 | }
|
---|
144 | }
|
---|
145 |
|
---|
146 | return exploder_plugins;
|
---|
147 | }
|
---|
148 |
|
---|
149 | public boolean isFileExplodable(File file)
|
---|
150 | {
|
---|
151 | ArrayList plugins_list = Plugins.getPluginsList();
|
---|
152 | for (int i = 0; i < plugins_list.size(); i++) {
|
---|
153 | Plugin plugin = (Plugin) plugins_list.get(i);
|
---|
154 | if (plugin.doesExplodeMetadataDatabases() == true && plugin.doesProcessFile(file) == true) {
|
---|
155 | return true;
|
---|
156 | }
|
---|
157 | }
|
---|
158 |
|
---|
159 | return false;
|
---|
160 | }
|
---|
161 |
|
---|
162 | // Works with replace_srcdoc_with_html.pl
|
---|
163 | public ArrayList getSrcReplacerPlugins(File file)
|
---|
164 | {
|
---|
165 | ArrayList srcreplacer_plugins = new ArrayList();
|
---|
166 | ArrayList plugins_list = Plugins.getPluginsList();
|
---|
167 | for (int i = 0; i < plugins_list.size(); i++) {
|
---|
168 | Plugin plugin = (Plugin) plugins_list.get(i);
|
---|
169 | if (plugin.doesReplaceSrcDocsWithHtml() == true && plugin.doesProcessFile(file)) {
|
---|
170 | srcreplacer_plugins.add(plugin);
|
---|
171 | }
|
---|
172 | }
|
---|
173 |
|
---|
174 | return srcreplacer_plugins;
|
---|
175 | }
|
---|
176 |
|
---|
177 | // Works with replace_srcdoc_with_html.pl
|
---|
178 | public boolean isFileSrcReplaceable(File file)
|
---|
179 | {
|
---|
180 | ArrayList plugins_list = Plugins.getPluginsList();
|
---|
181 | for (int i = 0; i < plugins_list.size(); i++) {
|
---|
182 | Plugin plugin = (Plugin) plugins_list.get(i);
|
---|
183 |
|
---|
184 | if (plugin.doesReplaceSrcDocsWithHtml() == true && plugin.doesProcessFile(file) == true) {
|
---|
185 | return true;
|
---|
186 | }
|
---|
187 | }
|
---|
188 |
|
---|
189 | return false;
|
---|
190 | }
|
---|
191 |
|
---|
192 | /** Method to assign a plugin
|
---|
193 | * @param plugin the Plugin to assign
|
---|
194 | */
|
---|
195 | private void assignPlugin(Plugin plugin) {
|
---|
196 | if(plugin.getName().equals(StaticStrings.RECPLUG_STR) || plugin.getName().equals(StaticStrings.ARCPLUG_STR) || plugin.getName().equals(StaticStrings.METADATAXMLPLUG_STR)) {
|
---|
197 | addAfter(plugin, separator_plugin); // Adds after separator
|
---|
198 | } else {
|
---|
199 | addBefore(plugin, separator_plugin);
|
---|
200 | }
|
---|
201 | }
|
---|
202 |
|
---|
203 |
|
---|
204 | /** Destructor. */
|
---|
205 | public void destroy()
|
---|
206 | {
|
---|
207 | CollectionManager.removeCollectionContentsChangedListener(this);
|
---|
208 |
|
---|
209 | if (controls != null) {
|
---|
210 | controls.destroy();
|
---|
211 | controls = null;
|
---|
212 | }
|
---|
213 | }
|
---|
214 |
|
---|
215 |
|
---|
216 | /** This function listens for new files being added to the collection and hints about suitable plugins. */
|
---|
217 | public void fileAddedToCollection(File file)
|
---|
218 | {
|
---|
219 | // First check the plugins already assigned in the collection
|
---|
220 | for (int i = 0; i < super.getSize(); i++) {
|
---|
221 | Plugin assigned_plugin = (Plugin) getElementAt(i);
|
---|
222 | if (assigned_plugin.isSeparator() == false && (assigned_plugin.doesProcessFile(file) == true || assigned_plugin.doesBlockFile(file) == true)) {
|
---|
223 | // This file will be processed by an assigned plugin, so no suggestion is necessary
|
---|
224 | DebugStream.println("Processed by assigned plugin: " + assigned_plugin);
|
---|
225 | return;
|
---|
226 | }
|
---|
227 | }
|
---|
228 |
|
---|
229 | // Next try the plugins NOT already assigned in the collection
|
---|
230 | ArrayList suitable_plugins = new ArrayList();
|
---|
231 | Object[] unassigned_plugins = getAvailablePlugins();
|
---|
232 | for (int i = 0; i < unassigned_plugins.length; i++) {
|
---|
233 | Plugin unassigned_plugin = (Plugin) unassigned_plugins[i];
|
---|
234 | if (unassigned_plugin.doesProcessFile(file) == true) {
|
---|
235 | DebugStream.println("Processed by unassigned plugin: " + unassigned_plugin);
|
---|
236 | suitable_plugins.add(unassigned_plugin);
|
---|
237 | }
|
---|
238 | }
|
---|
239 |
|
---|
240 | // If there appear to be no suitable plugins, warn the user about this and be done
|
---|
241 | if (suitable_plugins.size() == 0) {
|
---|
242 | String[] args = new String[1];
|
---|
243 | args[0] = file.getName();
|
---|
244 | WarningDialog warning_dialog = new WarningDialog("warning.NoPluginExpectedToProcessFile", Dictionary.get("NoPluginExpectedToProcessFile.Title"), Dictionary.get("NoPluginExpectedToProcessFile.Message", args), null, false);
|
---|
245 | warning_dialog.display();
|
---|
246 | warning_dialog.dispose();
|
---|
247 | return;
|
---|
248 | }
|
---|
249 |
|
---|
250 | // Generate a dialog
|
---|
251 | new PluginSuggestionPrompt(file.getName(), suitable_plugins);
|
---|
252 | }
|
---|
253 |
|
---|
254 |
|
---|
255 | /** Method to retrieve the control for this manager.
|
---|
256 | * @return the Control
|
---|
257 | */
|
---|
258 | public Control getControls() {
|
---|
259 | if(controls == null) {
|
---|
260 | // Build controls
|
---|
261 | controls = new PluginControl();
|
---|
262 | }
|
---|
263 | return controls;
|
---|
264 | }
|
---|
265 |
|
---|
266 |
|
---|
267 | /** Overrides getSize in DOMProxyListModel to take into account the row count modifier used to hide the last three rows in lower detail modes
|
---|
268 | * @return an int indicating the number of rows in the model, or more correctly the desired number of rows to display
|
---|
269 | */
|
---|
270 | public int getSize() {
|
---|
271 | int result = super.getSize();
|
---|
272 | if(modify_row_count) {
|
---|
273 | result = result-(NUM_FIXED_PLUGINS+1);
|
---|
274 | }
|
---|
275 | return result;
|
---|
276 | }
|
---|
277 |
|
---|
278 | /** Called when the detail mode has changed which in turn may cause several design elements to be available/hidden
|
---|
279 | * @param mode the new mode as an int
|
---|
280 | */
|
---|
281 | public void modeChanged(int mode) {
|
---|
282 | if(controls != null) {
|
---|
283 | ((PluginControl)controls).modeChanged(mode);
|
---|
284 | }
|
---|
285 | }
|
---|
286 |
|
---|
287 | /** Method to move a plugin in the list order.
|
---|
288 | * @param plugin the Plugin you want to move.
|
---|
289 | * @param direction true to move the plugin up, false to move it down.
|
---|
290 | * @param all true to move to move all the way, false for a single step.
|
---|
291 | */
|
---|
292 | // why are all the error notices there when the buttons are disabled is you cant move???
|
---|
293 | private void movePlugin(Plugin plugin, boolean direction, boolean all) {
|
---|
294 | // Can't ever move RecPlug or ArcPlug
|
---|
295 | if(super.getSize() < (NUM_FIXED_PLUGINS+2)) {
|
---|
296 | //DebugStream.println("Not enough plugins to allow moving.");
|
---|
297 | return;
|
---|
298 | }
|
---|
299 | if(plugin.getName().equals(StaticStrings.ARCPLUG_STR) || plugin.getName().equals(StaticStrings.RECPLUG_STR) || plugin.getName().equals(StaticStrings.METADATAXMLPLUG_STR)) {
|
---|
300 | JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CDM.Move.Fixed"), Dictionary.get("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE);
|
---|
301 | return;
|
---|
302 | }
|
---|
303 | if(all) {
|
---|
304 | // Move to top
|
---|
305 | if(direction) {
|
---|
306 | // Remove the moving plugin
|
---|
307 | remove(plugin);
|
---|
308 | // Retrieve the first plugin
|
---|
309 | Plugin first_plugin = (Plugin) getElementAt(0);
|
---|
310 | // Add the moving plugin before the first plugin
|
---|
311 | addBefore(plugin, first_plugin);
|
---|
312 | first_plugin = null;
|
---|
313 | }
|
---|
314 | else {
|
---|
315 | // Remove the moving plugin
|
---|
316 | remove(plugin);
|
---|
317 | // Add the moving plugin before the separator
|
---|
318 | addBefore(plugin, separator_plugin);
|
---|
319 | }
|
---|
320 | }
|
---|
321 | else {
|
---|
322 | // Try to move the plugin one step in the desired direction.
|
---|
323 | int index = indexOf(plugin);
|
---|
324 | ///ystem.err.println("Index of " + plugin + " = " + index);
|
---|
325 | if(direction) {
|
---|
326 | index--;
|
---|
327 | if(index < 0) {
|
---|
328 | String args[] = new String[2];
|
---|
329 | args[0] = Dictionary.get("CDM.PlugInManager.PlugIn_Str");
|
---|
330 | args[1] = plugin.getName();
|
---|
331 | JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CDM.Move.At_Top", args), Dictionary.get("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE);
|
---|
332 | return;
|
---|
333 | }
|
---|
334 | remove(plugin);
|
---|
335 | add(index, plugin);
|
---|
336 | }
|
---|
337 | else {
|
---|
338 | index++;
|
---|
339 | Plugin next_plugin = (Plugin) getElementAt(index);
|
---|
340 | if(next_plugin.isSeparator()) {
|
---|
341 | String args[] = new String[1];
|
---|
342 | args[0] = plugin.getName();
|
---|
343 | JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CDM.Move.Cannot", args), Dictionary.get("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE);
|
---|
344 | // Still not going to move RecPlug or ArcPlug.
|
---|
345 | return;
|
---|
346 | }
|
---|
347 | remove(plugin);
|
---|
348 | add(index, plugin);
|
---|
349 | }
|
---|
350 | }
|
---|
351 | }
|
---|
352 |
|
---|
353 | /** 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.
|
---|
354 | */
|
---|
355 | private void placeSeparator() {
|
---|
356 | ///ystem.err.println("Placing separator.");
|
---|
357 | int separator_index = super.getSize();
|
---|
358 | if(separator_index > 0) {
|
---|
359 | boolean found_fixed = false;
|
---|
360 | int index = separator_index - 1;
|
---|
361 | while(index > 0) {
|
---|
362 | Plugin plugin = (Plugin) getElementAt(index);
|
---|
363 | String name = plugin.getName();
|
---|
364 | if(name.equals(StaticStrings.RECPLUG_STR) || name.equals(StaticStrings.ARCPLUG_STR) || name.equals(StaticStrings.METADATAXMLPLUG_STR)) {
|
---|
365 | found_fixed = true;
|
---|
366 | index--;
|
---|
367 | }
|
---|
368 | else {
|
---|
369 | if(found_fixed) {
|
---|
370 | separator_index = index + 1;
|
---|
371 | index = -1;
|
---|
372 | }
|
---|
373 | else {
|
---|
374 | index--;
|
---|
375 | }
|
---|
376 | }
|
---|
377 | name = null;
|
---|
378 | plugin = null;
|
---|
379 | }
|
---|
380 | }
|
---|
381 | Element element = CollectionConfiguration.createElement(StaticStrings.PLUGIN_ELEMENT);
|
---|
382 | element.setAttribute(StaticStrings.TYPE_ATTRIBUTE, StaticStrings.SEPARATOR_ATTRIBUTE);
|
---|
383 | element.setAttribute(StaticStrings.SEPARATOR_ATTRIBUTE, StaticStrings.TRUE_STR);
|
---|
384 | separator_plugin = new Plugin(element, null);
|
---|
385 | ///atherer.println("Adding plugin separator at: " + separator_index);
|
---|
386 | add(separator_index, separator_plugin);
|
---|
387 | }
|
---|
388 |
|
---|
389 | /** 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.
|
---|
390 | * @param plugin The <strong>Plugin</strong> to remove.
|
---|
391 | */
|
---|
392 | private void removePlugin(Plugin plugin) {
|
---|
393 | remove(plugin);
|
---|
394 |
|
---|
395 | }
|
---|
396 |
|
---|
397 |
|
---|
398 | /** Inform the model to hide/show the last four lines on the list.
|
---|
399 | * @param modify_row_count true to hide the last four lines, false otherwise
|
---|
400 | */
|
---|
401 | private void setHideLines(boolean modify_row_count) {
|
---|
402 | this.modify_row_count = modify_row_count;
|
---|
403 | int original_size = super.getSize();
|
---|
404 | if(modify_row_count) {
|
---|
405 | fireIntervalRemoved(this, original_size - (NUM_FIXED_PLUGINS+2), original_size - 1);
|
---|
406 | }
|
---|
407 | else {
|
---|
408 | fireIntervalAdded(this, original_size - (NUM_FIXED_PLUGINS+2), original_size - 1);
|
---|
409 | }
|
---|
410 | }
|
---|
411 |
|
---|
412 | /** Determine the current separator index. */
|
---|
413 | private int findSeparatorIndex() {
|
---|
414 | int separator_index = super.getSize() - 1;
|
---|
415 | while(separator_index >= 0) {
|
---|
416 | Plugin search = (Plugin) getElementAt(separator_index);
|
---|
417 | if(search.isSeparator()) {
|
---|
418 | return separator_index;
|
---|
419 | }
|
---|
420 | separator_index--;
|
---|
421 | }
|
---|
422 | return separator_index;
|
---|
423 | }
|
---|
424 |
|
---|
425 |
|
---|
426 | /** A class which provodes controls for assigned and editing plugins. */
|
---|
427 | private class PluginControl
|
---|
428 | extends JPanel
|
---|
429 | implements Control {
|
---|
430 | /** Button for adding plugins. */
|
---|
431 | private JButton add = null;
|
---|
432 | /** Button for configuring the selected plugin. */
|
---|
433 | private JButton configure = null;
|
---|
434 | /** Button to move an assigned plugin one position lower in the order. */
|
---|
435 | private JButton move_down_button = null;
|
---|
436 | /** Button to move an assigned plugin one position higher in the order. */
|
---|
437 | private JButton move_up_button = null;
|
---|
438 | /** Button to remove the selected plugin. */
|
---|
439 | private JButton remove = null;
|
---|
440 | /** A combobox containing all of the known plugins, including those that may have already been assigned. */
|
---|
441 | private JComboBox plugin_combobox = null;
|
---|
442 | /** The label next to the plugin combobox. */
|
---|
443 | private JLabel plugin_label = null;
|
---|
444 | /** The label above the assigned plugin list. */
|
---|
445 | private JLabel plugin_list_label = null;
|
---|
446 | /** A list of assigned plugins. */
|
---|
447 | private JList plugin_list = null;
|
---|
448 | /** The area where the add, configure and remove buttons are placed. */
|
---|
449 | private JPanel button_pane = null;
|
---|
450 | /** The region which divides the central portion of the view into list and controls */
|
---|
451 | private JPanel central_pane = null;
|
---|
452 | /** The area where movement buttons are placed. */
|
---|
453 | private JPanel movement_pane = null;
|
---|
454 | /** The small region containing the plugin combobox and its label. */
|
---|
455 | private JPanel plugin_pane = null;
|
---|
456 | /** The pane containing the assigned plugin list and its label. */
|
---|
457 | private JPanel plugin_list_pane = null;
|
---|
458 |
|
---|
459 | /** Constructor.
|
---|
460 | */
|
---|
461 | public PluginControl()
|
---|
462 | {
|
---|
463 | // Create
|
---|
464 | add = new GLIButton(Dictionary.get("CDM.PlugInManager.Add"), Dictionary.get("CDM.PlugInManager.Add_Tooltip"));
|
---|
465 |
|
---|
466 | button_pane = new JPanel();
|
---|
467 | central_pane = new JPanel();
|
---|
468 | button_pane.setComponentOrientation(Dictionary.getOrientation());
|
---|
469 | central_pane.setComponentOrientation(Dictionary.getOrientation());
|
---|
470 |
|
---|
471 | configure = new GLIButton(Dictionary.get("CDM.PlugInManager.Configure"), Dictionary.get("CDM.PlugInManager.Configure_Tooltip"));
|
---|
472 | configure.setEnabled(false);
|
---|
473 |
|
---|
474 | JPanel header_pane = new DesignPaneHeader("CDM.GUI.Plugins", "plugins");
|
---|
475 | move_up_button = new GLIButton(Dictionary.get("CDM.Move.Move_Up"), JarTools.getImage("arrow-up.gif"), Dictionary.get("CDM.Move.Move_Up_Tooltip"));
|
---|
476 | move_up_button.setEnabled(false);
|
---|
477 |
|
---|
478 | move_down_button = new GLIButton(Dictionary.get("CDM.Move.Move_Down"), JarTools.getImage("arrow-down.gif"), Dictionary.get("CDM.Move.Move_Down_Tooltip"));
|
---|
479 | move_down_button.setEnabled(false);
|
---|
480 |
|
---|
481 | movement_pane = new JPanel();
|
---|
482 | movement_pane.setComponentOrientation(Dictionary.getOrientation());
|
---|
483 |
|
---|
484 | PluginComboboxListener picl = new PluginComboboxListener();
|
---|
485 | plugin_combobox = new JComboBox(getAvailablePlugins());
|
---|
486 | plugin_combobox.setOpaque(!Utility.isMac());
|
---|
487 | plugin_combobox.setEditable(false);
|
---|
488 | plugin_combobox.setComponentOrientation(Dictionary.getOrientation());
|
---|
489 |
|
---|
490 | picl.itemStateChanged(new ItemEvent(plugin_combobox, 0, null, ItemEvent.SELECTED));
|
---|
491 |
|
---|
492 | plugin_label = new JLabel(Dictionary.get("CDM.PlugInManager.PlugIn"));
|
---|
493 | plugin_label.setComponentOrientation(Dictionary.getOrientation());
|
---|
494 |
|
---|
495 | plugin_list = new JList(model);
|
---|
496 | plugin_list.setOpaque(true);
|
---|
497 | plugin_list.setCellRenderer(new ListRenderer());
|
---|
498 | plugin_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
---|
499 | plugin_list.setComponentOrientation(Dictionary.getOrientation());
|
---|
500 |
|
---|
501 | plugin_list_label = new JLabel(Dictionary.get("CDM.PlugInManager.Assigned"));
|
---|
502 | //plugin_list_label.setHorizontalAlignment(JLabel.CENTER);
|
---|
503 | plugin_list_label.setOpaque(true);
|
---|
504 | plugin_list_label.setComponentOrientation(Dictionary.getOrientation());
|
---|
505 |
|
---|
506 | plugin_list_pane = new JPanel();
|
---|
507 | plugin_list_pane.setComponentOrientation(Dictionary.getOrientation());
|
---|
508 |
|
---|
509 | plugin_pane = new JPanel();
|
---|
510 | plugin_pane.setOpaque(true);
|
---|
511 | plugin_pane.setComponentOrientation(Dictionary.getOrientation());
|
---|
512 |
|
---|
513 | remove = new GLIButton(Dictionary.get("CDM.PlugInManager.Remove"), Dictionary.get("CDM.PlugInManager.Remove_Tooltip"));
|
---|
514 | remove.setEnabled(false);
|
---|
515 |
|
---|
516 | // Listeners
|
---|
517 | add.addActionListener(new AddListener());
|
---|
518 | configure.addActionListener(new ConfigureListener());
|
---|
519 | MoveListener ml = new MoveListener();
|
---|
520 | move_down_button.addActionListener(ml);
|
---|
521 | move_down_button.addActionListener(CollectionDesignManager.all_change_listener);
|
---|
522 | move_up_button.addActionListener(ml);
|
---|
523 | move_up_button.addActionListener(CollectionDesignManager.all_change_listener);
|
---|
524 | plugin_combobox.addItemListener(picl);
|
---|
525 | remove.addActionListener(new RemoveListener());
|
---|
526 | remove.addActionListener(CollectionDesignManager.all_change_listener);
|
---|
527 | plugin_list.addMouseListener(new ClickListener());
|
---|
528 | plugin_list.addListSelectionListener(new ListListener());
|
---|
529 | picl = null;
|
---|
530 |
|
---|
531 | // Layout
|
---|
532 | movement_pane.setBorder(BorderFactory.createEmptyBorder(0,2,0,0));
|
---|
533 | movement_pane.setLayout(new GridLayout(4,1));
|
---|
534 | movement_pane.add(move_up_button);
|
---|
535 | JPanel tmp = new JPanel();
|
---|
536 | tmp.setComponentOrientation(Dictionary.getOrientation());
|
---|
537 | movement_pane.add(tmp);
|
---|
538 | tmp = new JPanel();
|
---|
539 | tmp.setComponentOrientation(Dictionary.getOrientation());
|
---|
540 | movement_pane.add(tmp);
|
---|
541 | movement_pane.add(move_down_button);
|
---|
542 |
|
---|
543 | plugin_list_pane.setLayout(new BorderLayout());
|
---|
544 | plugin_list_pane.add(plugin_list_label, BorderLayout.NORTH);
|
---|
545 | plugin_list_pane.add(new JScrollPane(plugin_list), BorderLayout.CENTER);
|
---|
546 | plugin_list_pane.add(movement_pane, BorderLayout.LINE_END);
|
---|
547 | modeChanged(Configuration.getMode()); // Whether the special plugins are hidden or not is mode dependant
|
---|
548 |
|
---|
549 | plugin_label.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
|
---|
550 |
|
---|
551 | plugin_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,0));
|
---|
552 | plugin_pane.setLayout(new BorderLayout(5,0));
|
---|
553 | plugin_pane.add(plugin_label, BorderLayout.LINE_START);
|
---|
554 | plugin_pane.add(plugin_combobox, BorderLayout.CENTER);
|
---|
555 |
|
---|
556 | button_pane.setLayout(new GridLayout(1,3));
|
---|
557 | button_pane.add(add);
|
---|
558 | button_pane.add(configure);
|
---|
559 | button_pane.add(remove);
|
---|
560 |
|
---|
561 | // Scope these mad bordering skillz.
|
---|
562 | JPanel temp = new JPanel(new BorderLayout());
|
---|
563 | temp.add(plugin_pane, BorderLayout.NORTH);
|
---|
564 | temp.add(button_pane, BorderLayout.SOUTH);
|
---|
565 | temp.setComponentOrientation(Dictionary.getOrientation());
|
---|
566 |
|
---|
567 | central_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
|
---|
568 | central_pane.setLayout(new BorderLayout());
|
---|
569 | central_pane.add(plugin_list_pane, BorderLayout.CENTER);
|
---|
570 | central_pane.add(temp, BorderLayout.SOUTH);
|
---|
571 |
|
---|
572 | setBorder(BorderFactory.createEmptyBorder(0,5,0,0));
|
---|
573 | setLayout(new BorderLayout());
|
---|
574 | add(header_pane, BorderLayout.NORTH);
|
---|
575 | add(central_pane, BorderLayout.CENTER);
|
---|
576 | }
|
---|
577 |
|
---|
578 | /** Method which acts like a destructor, tidying up references to persistant objects.
|
---|
579 | */
|
---|
580 | public void destroy() {
|
---|
581 | }
|
---|
582 |
|
---|
583 | /** This method is overridden to ensure the instructions are scrolled to top, before the super classes updateUI() is called.
|
---|
584 | no longer have instructions, do we still need updateUI???
|
---|
585 | */
|
---|
586 | public void gainFocus() {
|
---|
587 | super.updateUI();
|
---|
588 | }
|
---|
589 |
|
---|
590 | public void loseFocus() {
|
---|
591 | }
|
---|
592 |
|
---|
593 | /** 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
|
---|
594 | * @param mode the current mode as an int, which can be matched against static ints in the Configuration class
|
---|
595 | */
|
---|
596 | public void modeChanged(int mode) {
|
---|
597 | // 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
|
---|
598 | plugin_list.clearSelection();
|
---|
599 | plugin_combobox.setModel(new DefaultComboBoxModel(getAvailablePlugins()));
|
---|
600 | setHideLines(!(mode >= Configuration.EXPERT_MODE));
|
---|
601 |
|
---|
602 | plugin_list_pane.updateUI();
|
---|
603 | }
|
---|
604 |
|
---|
605 |
|
---|
606 | private class AddListener
|
---|
607 | implements ActionListener
|
---|
608 | {
|
---|
609 | public void actionPerformed(ActionEvent event)
|
---|
610 | {
|
---|
611 | if (plugin_combobox.getSelectedItem() != null) {
|
---|
612 | // This must be done on a new thread for the remote building code
|
---|
613 | new AddPluginTask(plugin_combobox.getSelectedItem().toString()).start();
|
---|
614 | }
|
---|
615 | }
|
---|
616 | }
|
---|
617 |
|
---|
618 |
|
---|
619 | private class AddPluginTask
|
---|
620 | extends Thread
|
---|
621 | {
|
---|
622 | private String plugin_name;
|
---|
623 |
|
---|
624 | public AddPluginTask(String plugin_name)
|
---|
625 | {
|
---|
626 | this.plugin_name = plugin_name;
|
---|
627 | }
|
---|
628 |
|
---|
629 | public void run()
|
---|
630 | {
|
---|
631 | // Retrieve the plugin
|
---|
632 | Plugin plugin = Plugins.getPlugin(plugin_name, true);
|
---|
633 | if (plugin == null) {
|
---|
634 | System.err.println("Error: getPlugin() returned null.");
|
---|
635 | return;
|
---|
636 | }
|
---|
637 |
|
---|
638 | // Create a new element in the DOM
|
---|
639 | Element new_plugin_element = CollectionConfiguration.createElement(StaticStrings.PLUGIN_ELEMENT);
|
---|
640 | new_plugin_element.setAttribute(StaticStrings.TYPE_ATTRIBUTE, plugin.getName());
|
---|
641 | Plugin new_plugin = new Plugin(new_plugin_element, plugin);
|
---|
642 |
|
---|
643 | ArgumentConfiguration ac = new ArgumentConfiguration(new_plugin);
|
---|
644 | ac.addOKButtonActionListener(CollectionDesignManager.all_change_listener);
|
---|
645 | if (ac.display()) {
|
---|
646 | assignPlugin(new_plugin);
|
---|
647 | plugin_list.setSelectedValue(new_plugin, true);
|
---|
648 | }
|
---|
649 | }
|
---|
650 | }
|
---|
651 |
|
---|
652 |
|
---|
653 | /** Listens for double clicks apon the list and react as if the configure button was pushed. */
|
---|
654 | private class ClickListener
|
---|
655 | extends MouseAdapter {
|
---|
656 | /** Called whenever the mouse is clicked over a registered component, we use this to chain through to the configure prompt.
|
---|
657 | * @param event A <strong>MouseEvent</strong> containing information about the mouse click.
|
---|
658 | */
|
---|
659 | public void mouseClicked(MouseEvent event) {
|
---|
660 | if(event.getClickCount() == 2 ) {
|
---|
661 | if(!plugin_list.isSelectionEmpty()) {
|
---|
662 | Plugin plugin = (Plugin) plugin_list.getSelectedValue();
|
---|
663 | if(!plugin.isSeparator()) {
|
---|
664 | ArgumentConfiguration ac = new ArgumentConfiguration(plugin);
|
---|
665 | ac.addOKButtonActionListener(CollectionDesignManager.all_change_listener);
|
---|
666 | if (ac.display()) {
|
---|
667 | refresh(plugin);
|
---|
668 | }
|
---|
669 | ac.destroy();
|
---|
670 | ac = null;
|
---|
671 | }
|
---|
672 | }
|
---|
673 | }
|
---|
674 | }
|
---|
675 | }
|
---|
676 |
|
---|
677 | /** 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.
|
---|
678 | * @see org.greenstone.gatherer.cdm.ArgumentConfiguration
|
---|
679 | */
|
---|
680 | private class ConfigureListener
|
---|
681 | implements ActionListener {
|
---|
682 | /** 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.
|
---|
683 | * @param event An <strong>ActionEvent</strong> containing information garnered from the control action.
|
---|
684 | */
|
---|
685 | public void actionPerformed(ActionEvent event) {
|
---|
686 | if(!plugin_list.isSelectionEmpty()) {
|
---|
687 | Plugin plugin = (Plugin) plugin_list.getSelectedValue();
|
---|
688 | if(!plugin.isSeparator()) {
|
---|
689 | ArgumentConfiguration ac = new ArgumentConfiguration(plugin);
|
---|
690 | ac.addOKButtonActionListener(CollectionDesignManager.all_change_listener);
|
---|
691 | if (ac.display()) {
|
---|
692 | refresh(plugin);
|
---|
693 | }
|
---|
694 | ac.destroy();
|
---|
695 | ac = null;
|
---|
696 | }
|
---|
697 | }
|
---|
698 | }
|
---|
699 | }
|
---|
700 |
|
---|
701 | /** 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 */
|
---|
702 | private class ListListener
|
---|
703 | implements ListSelectionListener {
|
---|
704 |
|
---|
705 | public void valueChanged(ListSelectionEvent e) {
|
---|
706 | if (!e.getValueIsAdjusting()) { // we get two events for one change in list selection - use the false one (the second one)
|
---|
707 | if (plugin_list.isSelectionEmpty()) {
|
---|
708 | move_up_button.setEnabled(false);
|
---|
709 | move_down_button.setEnabled(false);
|
---|
710 | configure.setEnabled(false);
|
---|
711 | remove.setEnabled(false);
|
---|
712 | } else {
|
---|
713 | Plugin selected_plugin = (Plugin) plugin_list.getSelectedValue();
|
---|
714 | if(selected_plugin.isSeparator()) {
|
---|
715 | move_up_button.setEnabled(false);
|
---|
716 | move_down_button.setEnabled(false);
|
---|
717 | configure.setEnabled(false);
|
---|
718 | remove.setEnabled(false);
|
---|
719 | } else {
|
---|
720 | configure.setEnabled(true);
|
---|
721 | String plugin_name = selected_plugin.getName();
|
---|
722 | // Some buttons are only available for plugins other than ArcPlug and RecPlug
|
---|
723 | if(plugin_name.equals(StaticStrings.ARCPLUG_STR) || plugin_name.equals(StaticStrings.RECPLUG_STR) || plugin_name.equals(StaticStrings.METADATAXMLPLUG_STR)) {
|
---|
724 | move_up_button.setEnabled(false);
|
---|
725 | move_down_button.setEnabled(false);
|
---|
726 | remove.setEnabled(false);
|
---|
727 | }
|
---|
728 |
|
---|
729 | else {
|
---|
730 | // don't let people remove special plugins such GreenstoneXMLPlug and GreenstoneMETSPlug,
|
---|
731 | // unless they are in expert mode or above
|
---|
732 | int mode = Configuration.getMode();
|
---|
733 | for (int i=0; i<StaticStrings.KEEP_PLUG.length; i++) {
|
---|
734 | if ((plugin_name.equals(StaticStrings.KEEP_PLUG[i])) &&
|
---|
735 | (mode < Configuration.EXPERT_MODE)) {
|
---|
736 | remove.setEnabled(false);
|
---|
737 | break;
|
---|
738 | } else {
|
---|
739 | remove.setEnabled(true);
|
---|
740 | }
|
---|
741 | }
|
---|
742 |
|
---|
743 | // Move ups are only enabled if the selected plugin isn't already at the top
|
---|
744 | Plugin first_plugin = (Plugin) getElementAt(0);
|
---|
745 | if(!first_plugin.equals(selected_plugin)) {
|
---|
746 | move_up_button.setEnabled(true);
|
---|
747 | } else {
|
---|
748 | move_up_button.setEnabled(false);
|
---|
749 | }
|
---|
750 | // And move downs are only allowed when the selected plugin isn't at an index one less than the separator line.
|
---|
751 | int separator_index = findSeparatorIndex();
|
---|
752 | int selected_index = plugin_list.getSelectedIndex();
|
---|
753 | if(selected_index < separator_index - 1) {
|
---|
754 | move_down_button.setEnabled(true);
|
---|
755 | } else {
|
---|
756 | move_down_button.setEnabled(false);
|
---|
757 | }
|
---|
758 | }
|
---|
759 | selected_plugin = null;
|
---|
760 | plugin_name = null;
|
---|
761 | }
|
---|
762 | }
|
---|
763 | }
|
---|
764 | }
|
---|
765 | }
|
---|
766 |
|
---|
767 | /** A special list renderer which is able to render separating lines as well. */
|
---|
768 | private class ListRenderer
|
---|
769 | extends DefaultListCellRenderer {
|
---|
770 | /** 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.
|
---|
771 | * @param list - The <strong>JList</strong> we're painting.
|
---|
772 | * @param value - The value returned by list.getModel().getElementAt(index) as an <strong>Object</strong>.
|
---|
773 | * @param index - The cells index as an <i>int</i>.
|
---|
774 | * @param isSelected - <i>true</i> if the specified cell was selected.
|
---|
775 | * @param cellHasFocus - <i>true</i> if the specified cell has the focus.
|
---|
776 | * @return A <strong>Component</strong> whose paint() method will render the specified value.
|
---|
777 | * @see javax.swing.JList
|
---|
778 | * @see javax.swing.JSeparator
|
---|
779 | * @see javax.swing.ListModel
|
---|
780 | * @see javax.swing.ListSelectionModel
|
---|
781 | */
|
---|
782 | public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
|
---|
783 | Plugin plugin = (Plugin) value;
|
---|
784 | if(plugin.isSeparator()) {
|
---|
785 | return separator;
|
---|
786 | }
|
---|
787 | else {
|
---|
788 | return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
---|
789 | }
|
---|
790 | }
|
---|
791 | }
|
---|
792 |
|
---|
793 |
|
---|
794 | /** 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. */
|
---|
795 | private class MoveListener
|
---|
796 | implements ActionListener {
|
---|
797 | /** 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.
|
---|
798 | * @param event An <strong>ActionEvent</strong> containing information garnered from the control action.
|
---|
799 | */
|
---|
800 | public void actionPerformed(ActionEvent event) {
|
---|
801 | if (!plugin_list.isSelectionEmpty()) {
|
---|
802 | Object object = plugin_list.getSelectedValue();
|
---|
803 | if (object instanceof Plugin) {
|
---|
804 | Plugin plugin = (Plugin) object;
|
---|
805 | if (event.getSource() == move_up_button) {
|
---|
806 | movePlugin(plugin, true, false);
|
---|
807 | }
|
---|
808 | else if (event.getSource() == move_down_button) {
|
---|
809 | movePlugin(plugin, false, false);
|
---|
810 | }
|
---|
811 | plugin_list.setSelectedValue(plugin, true);
|
---|
812 | }
|
---|
813 | }
|
---|
814 | }
|
---|
815 | }
|
---|
816 |
|
---|
817 | /** This listener reacts to changes in the current selection of the plugin combobox. */
|
---|
818 | private class PluginComboboxListener
|
---|
819 | implements ItemListener {
|
---|
820 | /** When a user selects a certain plugin, update the tooltip to show the plugin description. */
|
---|
821 | public void itemStateChanged(ItemEvent event) {
|
---|
822 | if(event.getStateChange() == ItemEvent.SELECTED) {
|
---|
823 | // Retrieve the selected plugin
|
---|
824 | Object current_selection = plugin_combobox.getSelectedItem();
|
---|
825 | // And reset the tooltip. If the plugin is null or is a string, then go back to the default message
|
---|
826 | if(current_selection == null || current_selection instanceof String) {
|
---|
827 | plugin_combobox.setToolTipText(Dictionary.get("CDM.PlugInManager.PlugIn_Tooltip"));
|
---|
828 | }
|
---|
829 | else {
|
---|
830 | Plugin current_plugin = (Plugin) current_selection;
|
---|
831 | plugin_combobox.setToolTipText(Utility.formatHTMLWidth(current_plugin.getDescription(), 40));
|
---|
832 | current_plugin = null;
|
---|
833 | }
|
---|
834 | current_selection = null;
|
---|
835 | }
|
---|
836 | }
|
---|
837 | }
|
---|
838 |
|
---|
839 | /** This class listens for actions upon the remove button in the controls, and if detected calls the <i>removePlugin()</i> method.
|
---|
840 | */
|
---|
841 | private class RemoveListener
|
---|
842 | implements ActionListener {
|
---|
843 | /** 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.
|
---|
844 | * @param event An <strong>ActionEvent</strong> containing information garnered from the control action.
|
---|
845 | */
|
---|
846 | public void actionPerformed(ActionEvent event) {
|
---|
847 | int selected_index = plugin_list.getSelectedIndex();
|
---|
848 | if(selected_index != -1) {
|
---|
849 | Plugin selected_plugin = (Plugin) plugin_list.getSelectedValue();
|
---|
850 | removePlugin(selected_plugin);
|
---|
851 | selected_plugin = null;
|
---|
852 | // Refresh the available plugins
|
---|
853 | plugin_combobox.setModel(new DefaultComboBoxModel(getAvailablePlugins()));
|
---|
854 |
|
---|
855 | // Select the next plugin if available
|
---|
856 | if(selected_index < plugin_list.getModel().getSize()) {
|
---|
857 | // If the new selection is above the separator we can remove it
|
---|
858 | if(selected_index < findSeparatorIndex()) {
|
---|
859 | plugin_list.setSelectedIndex(selected_index);
|
---|
860 |
|
---|
861 | // don't let people remove special plugins such GAPlug an METSPlug,
|
---|
862 | // unless they are in expert mode or above
|
---|
863 | int mode = Configuration.getMode();
|
---|
864 | for (int i=0; i<StaticStrings.KEEP_PLUG.length; i++) {
|
---|
865 | String selected_plugin_name
|
---|
866 | = ((Plugin)plugin_list.getSelectedValue()).getName();
|
---|
867 |
|
---|
868 | if (selected_plugin_name.equals(StaticStrings.METADATAXMLPLUG_STR)) {
|
---|
869 | //this plug cannot be removed under any conditions.
|
---|
870 | remove.setEnabled(false);
|
---|
871 | }else if ((selected_plugin_name.equals(StaticStrings.KEEP_PLUG[i])) &&
|
---|
872 | (mode < Configuration.EXPERT_MODE)) {
|
---|
873 | remove.setEnabled(false);
|
---|
874 | break;
|
---|
875 | } else {
|
---|
876 | remove.setEnabled(true);
|
---|
877 | }
|
---|
878 | }
|
---|
879 | }
|
---|
880 | // Otherwise select the first non-removable plugin
|
---|
881 | else {
|
---|
882 | plugin_list.setSelectedIndex(selected_index + 1);
|
---|
883 | remove.setEnabled(false);
|
---|
884 | }
|
---|
885 | } else {
|
---|
886 | remove.setEnabled(false);
|
---|
887 | }
|
---|
888 | } else {
|
---|
889 | remove.setEnabled(false);
|
---|
890 | }
|
---|
891 | }
|
---|
892 | }
|
---|
893 | }
|
---|
894 |
|
---|
895 |
|
---|
896 | private class PluginSuggestionPrompt
|
---|
897 | extends ModalDialog
|
---|
898 | implements ActionListener
|
---|
899 | {
|
---|
900 | private Dimension size = new Dimension(480, 240);
|
---|
901 | private GComboBox suitable_plugins_combobox = null;
|
---|
902 | private GLIButton add_button = null;
|
---|
903 | private GLIButton ignore_button = null;
|
---|
904 |
|
---|
905 | public PluginSuggestionPrompt(String filename, ArrayList suitable_plugins)
|
---|
906 | {
|
---|
907 | super(Gatherer.g_man, true);
|
---|
908 | setModal(true);
|
---|
909 | setSize(size);
|
---|
910 | setTitle(Dictionary.get("CDM.PluginManager.SuggestedPluginListTitle"));
|
---|
911 | this.setComponentOrientation(Dictionary.getOrientation());
|
---|
912 |
|
---|
913 | String[] args = new String[1];
|
---|
914 | args[0] = filename;
|
---|
915 |
|
---|
916 | JTextArea instructions_textarea = new JTextArea(Dictionary.get("CDM.PluginManager.Plugin_Suggestion_Prompt", args));
|
---|
917 | instructions_textarea.setCaretPosition(0);
|
---|
918 | instructions_textarea.setEditable(false);
|
---|
919 | instructions_textarea.setLineWrap(true);
|
---|
920 | instructions_textarea.setRows(5);
|
---|
921 | instructions_textarea.setWrapStyleWord(true);
|
---|
922 | instructions_textarea.setComponentOrientation(Dictionary.getOrientation());
|
---|
923 |
|
---|
924 | JLabel suitable_plugins_label = new JLabel(Dictionary.get("CDM.PlugInManager.PlugIn"));
|
---|
925 | suitable_plugins_label.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
|
---|
926 | suitable_plugins_label.setComponentOrientation(Dictionary.getOrientation());
|
---|
927 |
|
---|
928 | suitable_plugins_combobox = new GComboBox(suitable_plugins);
|
---|
929 | suitable_plugins_combobox.setBackgroundNonSelectionColor(Configuration.getColor("coloring.editable_background", false));
|
---|
930 | suitable_plugins_combobox.setBackgroundSelectionColor(Configuration.getColor("coloring.collection_selection_background", false));
|
---|
931 | suitable_plugins_combobox.setTextNonSelectionColor(Configuration.getColor("coloring.workspace_tree_foreground", false));
|
---|
932 | suitable_plugins_combobox.setTextSelectionColor(Configuration.getColor("coloring.collection_selection_foreground", false));
|
---|
933 | suitable_plugins_combobox.setComponentOrientation(Dictionary.getOrientation());
|
---|
934 |
|
---|
935 | JPanel suitable_plugins_pane = new JPanel();
|
---|
936 | suitable_plugins_pane.setComponentOrientation(Dictionary.getOrientation());
|
---|
937 | //suitable_plugins_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,0));
|
---|
938 | suitable_plugins_pane.setLayout(new BorderLayout(5,0));
|
---|
939 | suitable_plugins_pane.add(suitable_plugins_label, BorderLayout.LINE_START);
|
---|
940 | suitable_plugins_pane.add(suitable_plugins_combobox, BorderLayout.CENTER);
|
---|
941 |
|
---|
942 | add_button = new GLIButton(Dictionary.get("CDM.PlugInManager.QuickAdd"), Dictionary.get("CDM.PlugInManager.Add_Tooltip"));
|
---|
943 | ignore_button = new GLIButton(Dictionary.get("CDM.PlugInManager.Ignore"), Dictionary.get("CDM.PlugInManager.Ignore_Tooltip"));
|
---|
944 |
|
---|
945 | add_button.addActionListener(this);
|
---|
946 | ignore_button.addActionListener(this);
|
---|
947 |
|
---|
948 | JPanel button_pane = new JPanel();
|
---|
949 | button_pane.setLayout(new GridLayout(1,2,5,0));
|
---|
950 | button_pane.add(add_button);
|
---|
951 | button_pane.add(ignore_button);
|
---|
952 | button_pane.setComponentOrientation(Dictionary.getOrientation());
|
---|
953 |
|
---|
954 | JPanel controls_pane = new JPanel();
|
---|
955 | controls_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
|
---|
956 | controls_pane.setLayout(new GridLayout(2,1,0,5));
|
---|
957 | controls_pane.add(suitable_plugins_pane);
|
---|
958 | controls_pane.add(button_pane);
|
---|
959 | controls_pane.setComponentOrientation(Dictionary.getOrientation());
|
---|
960 |
|
---|
961 | JPanel content_pane = (JPanel) getContentPane();
|
---|
962 | content_pane.setComponentOrientation(Dictionary.getOrientation());
|
---|
963 | content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
|
---|
964 | content_pane.setLayout(new BorderLayout());
|
---|
965 | content_pane.add(instructions_textarea, BorderLayout.CENTER);
|
---|
966 | content_pane.add(controls_pane, BorderLayout.SOUTH);
|
---|
967 |
|
---|
968 | // Show
|
---|
969 | Dimension screen_size = Configuration.screen_size;
|
---|
970 | setLocation((screen_size.width - size.width) / 2, (screen_size.height - size.height) / 2);
|
---|
971 | setVisible(true);
|
---|
972 | }
|
---|
973 |
|
---|
974 |
|
---|
975 | public void actionPerformed(ActionEvent event)
|
---|
976 | {
|
---|
977 | // Close the dialog
|
---|
978 | setVisible(false);
|
---|
979 |
|
---|
980 | if (event.getSource() == add_button) {
|
---|
981 | AddPluginWithoutConfigurationTask add_plugin_task = new AddPluginWithoutConfigurationTask(suitable_plugins_combobox.getSelectedItem().toString());
|
---|
982 | add_plugin_task.start();
|
---|
983 |
|
---|
984 | // We have to wait for this task to complete before continuing, otherwise
|
---|
985 | // we might offer to add the same plugin again before the task has completed
|
---|
986 | try {
|
---|
987 | add_plugin_task.join();
|
---|
988 | }
|
---|
989 | catch (Exception exception) {
|
---|
990 | DebugStream.printStackTrace(exception);
|
---|
991 | }
|
---|
992 | }
|
---|
993 | }
|
---|
994 |
|
---|
995 |
|
---|
996 | private class AddPluginWithoutConfigurationTask
|
---|
997 | extends Thread
|
---|
998 | {
|
---|
999 | private String plugin_name;
|
---|
1000 |
|
---|
1001 | public AddPluginWithoutConfigurationTask(String plugin_name)
|
---|
1002 | {
|
---|
1003 | this.plugin_name = plugin_name;
|
---|
1004 | }
|
---|
1005 |
|
---|
1006 | public void run()
|
---|
1007 | {
|
---|
1008 | // Retrieve the plugin
|
---|
1009 | Plugin plugin = Plugins.getPlugin(plugin_name, true);
|
---|
1010 | if (plugin == null) {
|
---|
1011 | System.err.println("Error: getPlugin() returned null.");
|
---|
1012 | return;
|
---|
1013 | }
|
---|
1014 |
|
---|
1015 | // Create a new element in the DOM
|
---|
1016 | Element new_plugin_element = CollectionConfiguration.createElement(StaticStrings.PLUGIN_ELEMENT);
|
---|
1017 | new_plugin_element.setAttribute(StaticStrings.TYPE_ATTRIBUTE, plugin.getName());
|
---|
1018 | Plugin new_plugin = new Plugin(new_plugin_element, plugin);
|
---|
1019 |
|
---|
1020 | // Just assign the plugin with no argument configuration
|
---|
1021 | assignPlugin(new_plugin);
|
---|
1022 | Gatherer.c_man.getCollection().cdm.save();
|
---|
1023 | }
|
---|
1024 | }
|
---|
1025 | }
|
---|
1026 |
|
---|
1027 |
|
---|
1028 | /** Creates a list separator.
|
---|
1029 | * Found on Google Groups. Code courtesy of Paul Farwell.
|
---|
1030 | */
|
---|
1031 | private JPanel getSeparator() {
|
---|
1032 | // We put the separator inside a panel to control its appearance
|
---|
1033 | JPanel _sepPanel = new JPanel();
|
---|
1034 | _sepPanel.setOpaque(false);
|
---|
1035 | _sepPanel.setBorder(BorderFactory.createEmptyBorder(1, 3, 1, 3));
|
---|
1036 | _sepPanel.setLayout(new BoxLayout(_sepPanel, BoxLayout.Y_AXIS));
|
---|
1037 | _sepPanel.add(Box.createRigidArea(new Dimension(0, 4)));
|
---|
1038 | // 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
|
---|
1039 | _sepPanel.add(new BasicSeparator());
|
---|
1040 | _sepPanel.add(Box.createRigidArea(new Dimension(0, 4)));
|
---|
1041 | return _sepPanel;
|
---|
1042 | }
|
---|
1043 |
|
---|
1044 | /** 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. */
|
---|
1045 | private static class BasicSeparator
|
---|
1046 | extends JSeparator {
|
---|
1047 |
|
---|
1048 | private ComponentUI basic_ui;
|
---|
1049 |
|
---|
1050 | public BasicSeparator() {
|
---|
1051 | super();
|
---|
1052 | basic_ui = new BasicSeparatorUI();
|
---|
1053 | }
|
---|
1054 |
|
---|
1055 | public void paintComponent(Graphics g) {
|
---|
1056 | if (basic_ui != null) {
|
---|
1057 | basic_ui.update(g, this);
|
---|
1058 | }
|
---|
1059 | }
|
---|
1060 | }
|
---|
1061 | }
|
---|