001 /*
002 * Copyright (c) 1995-2010, The University of Sheffield. See the file
003 * COPYRIGHT.txt in the software or at http://gate.ac.uk/gate/COPYRIGHT.txt
004 * Copyright (c) 2009, Ontotext AD.
005 *
006 * This file is part of GATE (see http://gate.ac.uk/), and is free
007 * software, licenced under the GNU Library General Public License,
008 * Version 2, June 1991 (in the distribution as file licence.html,
009 * and also available at http://gate.ac.uk/gate/licence.html).
010 *
011 * PluginManagerUI.java
012 *
013 * Valentin Tablan, 21-Jul-2004
014 *
015 * $Id: PluginManagerUI.java 13565 2011-03-26 23:03:34Z johann_p $
016 */
017
018 package gate.gui;
019
020 import java.awt.*;
021 import java.awt.event.*;
022 import java.io.File;
023 import java.net.MalformedURLException;
024 import java.net.URISyntaxException;
025 import java.net.URL;
026 import java.util.*;
027 import java.util.Timer;
028 import java.util.List;
029 import java.text.Collator;
030 import java.util.logging.Level;
031 import java.util.logging.Logger;
032 import javax.swing.*;
033 import javax.swing.border.TitledBorder;
034 import javax.swing.event.ListSelectionEvent;
035 import javax.swing.event.ListSelectionListener;
036 import javax.swing.event.DocumentListener;
037 import javax.swing.event.DocumentEvent;
038 import javax.swing.table.*;
039 import gate.Gate;
040 import gate.GateConstants;
041 import gate.swing.XJTable;
042 import gate.swing.XJFileChooser;
043 import gate.util.*;
044
045 /**
046 * This is the user interface used for plugins management.
047 */
048 public class PluginManagerUI extends JDialog implements GateConstants{
049
050 public PluginManagerUI(Frame owner){
051 super(owner);
052 initLocalData();
053 initGUI();
054 initListeners();
055 }
056
057
058 protected void initLocalData(){
059 loadNowByURL = new HashMap<URL, Boolean>();
060 loadAlwaysByURL = new HashMap<URL, Boolean>();
061 visibleRows = new ArrayList<URL>(Gate.getKnownPlugins());
062 }
063
064 protected void initGUI(){
065 setTitle("Plugin Management Console");
066 JPanel leftPanel = new JPanel(new BorderLayout());
067
068 JPanel leftTopPanel = new JPanel(new BorderLayout());
069 JLabel titleLabel = new JLabel("Known CREOLE directories");
070 titleLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 40));
071 leftTopPanel.add(titleLabel, BorderLayout.WEST);
072 JPanel leftTopCenterPanel = new JPanel(new BorderLayout());
073 leftTopCenterPanel.add(new JLabel("Filter:"), BorderLayout.WEST);
074 filterTextField = new JTextField();
075 filterTextField.setToolTipText("Type some text to filter the table rows.");
076 leftTopCenterPanel.add(filterTextField, BorderLayout.CENTER);
077 JButton clearFilterButton = new JButton(
078 new AbstractAction("", MainFrame.getIcon("exit.gif")) {
079 { this.putValue(MNEMONIC_KEY, KeyEvent.VK_BACK_SPACE);
080 this.putValue(SHORT_DESCRIPTION, "Clear text field"); }
081 public void actionPerformed(ActionEvent e) {
082 filterTextField.setText("");
083 filterTextField.requestFocusInWindow();
084 }
085 });
086 clearFilterButton.setBorder(BorderFactory.createEmptyBorder());
087 clearFilterButton.setIconTextGap(0);
088 leftTopCenterPanel.add(clearFilterButton, BorderLayout.EAST);
089 leftTopPanel.add(leftTopCenterPanel, BorderLayout.CENTER);
090 leftPanel.add(leftTopPanel, BorderLayout.NORTH);
091
092 mainTableModel = new MainTableModel();
093 mainTable = new XJTable();
094 mainTable.setTabSkipUneditableCell(true);
095 mainTable.setModel(mainTableModel);
096 mainTable.setSortedColumn(NAME_COLUMN);
097 Collator collator = Collator.getInstance(Locale.ENGLISH);
098 collator.setStrength(Collator.TERTIARY);
099 mainTable.setComparator(NAME_COLUMN, collator);
100 mainTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
101 DeleteColumnCellRendererEditor rendererEditor =
102 new DeleteColumnCellRendererEditor();
103 mainTable.getColumnModel().getColumn(DELETE_COLUMN).
104 setCellEditor(rendererEditor);
105 mainTable.getColumnModel().getColumn(DELETE_COLUMN).
106 setCellRenderer(rendererEditor);
107 mainTable.getColumnModel().getColumn(ICON_COLUMN).
108 setCellRenderer(new IconTableCellRenderer());
109
110 resourcesListModel = new ResourcesListModel();
111 resourcesList = new JList(resourcesListModel);
112 resourcesList.setCellRenderer(new ResourcesListCellRenderer());
113 resourcesList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
114 //enable tooltips
115 ToolTipManager.sharedInstance().registerComponent(resourcesList);
116
117 mainSplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true);
118 mainSplit.setResizeWeight(0.70);
119 mainSplit.setContinuousLayout(true);
120 JScrollPane scroller = new JScrollPane(mainTable);
121 leftPanel.add(scroller, BorderLayout.CENTER);
122 mainSplit.setLeftComponent(leftPanel);
123
124 scroller = new JScrollPane(resourcesList);
125 scroller.setBorder(BorderFactory.createTitledBorder(
126 scroller.getBorder(),
127 "CREOLE resources in directory",
128 TitledBorder.LEFT, TitledBorder.ABOVE_TOP));
129 mainSplit.setRightComponent(scroller);
130
131 getContentPane().setLayout(new GridBagLayout());
132 GridBagConstraints constraints = new GridBagConstraints();
133 constraints.insets = new Insets(2, 2, 2, 2);
134 constraints.fill = GridBagConstraints.BOTH;
135 constraints.anchor = GridBagConstraints.WEST;
136 constraints.gridy = 0;
137 constraints.weightx = 1;
138 constraints.weighty = 1;
139 getContentPane().add(mainSplit, constraints);
140
141 constraints.gridy = 1;
142 constraints.weighty = 0;
143 Box hBox = Box.createHorizontalBox();
144 hBox.add(new JButton(new AddCreoleRepositoryAction()));
145 hBox.add(Box.createHorizontalGlue());
146 getContentPane().add(hBox, constraints);
147
148 constraints.gridy = 2;
149 constraints.anchor = GridBagConstraints.CENTER;
150 constraints.fill = GridBagConstraints.NONE;
151 hBox = Box.createHorizontalBox();
152 JButton okButton = new JButton(new OkAction());
153 hBox.add(okButton);
154 hBox.add(Box.createHorizontalStrut(5));
155 hBox.add(new JButton(new CancelAction()));
156 hBox.add(Box.createHorizontalStrut(5));
157 hBox.add(new JButton(new HelpAction()));
158 constraints.insets = new Insets(2, 2, 8, 2);
159 getContentPane().add(hBox, constraints);
160 getRootPane().setDefaultButton(okButton);
161 }
162
163 protected void initListeners(){
164 mainTable.getSelectionModel().addListSelectionListener(
165 new ListSelectionListener(){
166 public void valueChanged(ListSelectionEvent e){
167 if (!e.getValueIsAdjusting()) {
168 resourcesListModel.dataChanged();
169 }
170 }
171 });
172
173 // when typing a character in the table, use it for filtering
174 mainTable.addKeyListener(new KeyAdapter() {
175 public void keyTyped(KeyEvent e) {
176 if (e.getKeyChar() != KeyEvent.VK_TAB
177 && e.getKeyChar() != KeyEvent.VK_SPACE
178 && e.getKeyChar() != KeyEvent.VK_BACK_SPACE
179 && e.getKeyChar() != KeyEvent.VK_DELETE) {
180 filterTextField.requestFocusInWindow();
181 filterTextField.setText(String.valueOf(e.getKeyChar()));
182 }
183 }
184 });
185
186 addComponentListener(new ComponentAdapter(){
187 public void componentShown(ComponentEvent e){
188 SwingUtilities.invokeLater(new Runnable() { public void run() {
189 mainSplit.setDividerLocation(0.8);
190 }});
191 }
192 });
193
194 // show only the rows containing the text from filterTextField
195 filterTextField.getDocument().addDocumentListener(new DocumentListener() {
196 private Timer timer = new Timer("Plugin manager table rows filter", true);
197 private TimerTask timerTask;
198 public void changedUpdate(DocumentEvent e) { /* do nothing */ }
199 public void insertUpdate(DocumentEvent e) { update(); }
200 public void removeUpdate(DocumentEvent e) { update(); }
201 private void update() {
202 if (timerTask != null) { timerTask.cancel(); }
203 Date timeToRun = new Date(System.currentTimeMillis() + 300);
204 timerTask = new TimerTask() { public void run() {
205 filterRows(filterTextField.getText());
206 }};
207 // add a delay
208 timer.schedule(timerTask, timeToRun);
209 }
210 });
211
212 // Up/Down key events in filterTextField are transferred to the table
213 filterTextField.addKeyListener(new KeyAdapter() {
214 public void keyPressed(KeyEvent e) {
215 if (e.getKeyCode() == KeyEvent.VK_UP
216 || e.getKeyCode() == KeyEvent.VK_DOWN
217 || e.getKeyCode() == KeyEvent.VK_PAGE_UP
218 || e.getKeyCode() == KeyEvent.VK_PAGE_DOWN) {
219 mainTable.dispatchEvent(e);
220 }
221 }
222 });
223
224 // disable Enter key in the table so this key will confirm the dialog
225 InputMap inputMap = mainTable.getInputMap(
226 JTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
227 KeyStroke enter = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
228 inputMap.put(enter, "none");
229
230 // define keystrokes action bindings at the level of the main window
231 inputMap = ((JComponent)this.getContentPane())
232 .getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
233 ActionMap actionMap = ((JComponent)this.getContentPane()).getActionMap();
234 inputMap.put(KeyStroke.getKeyStroke("ENTER"), "Apply");
235 actionMap.put("Apply", new OkAction());
236 inputMap.put(KeyStroke.getKeyStroke("ESCAPE"), "Cancel");
237 actionMap.put("Cancel", new CancelAction());
238 inputMap.put(KeyStroke.getKeyStroke("F1"), "Help");
239 actionMap.put("Help", new HelpAction());
240 }
241
242 private void filterRows(String rowFilter) {
243 final String filter = rowFilter.trim().toLowerCase();
244 final String previousURL = mainTable.getSelectedRow() == -1 ? "" :
245 (String) mainTable.getValueAt(mainTable.getSelectedRow(),
246 mainTable.convertColumnIndexToView(URL_COLUMN));
247 ArrayList<URL> previousVisibleRows = new ArrayList<URL>(visibleRows);
248 if (filter.length() < 2) {
249 // one character or less, don't filter rows
250 visibleRows = new ArrayList<URL>(Gate.getKnownPlugins());
251 } else {
252 // filter rows case insensitively on each plugin URL and its resources
253 visibleRows.clear();
254 for (int i = 0; i < Gate.getKnownPlugins().size(); i++) {
255 Gate.DirectoryInfo dInfo = Gate.getDirectoryInfo(
256 Gate.getKnownPlugins().get(i));
257 String url = dInfo.getUrl().toString();
258 String resources = "";
259 for (int j = 0; j < dInfo.getResourceInfoList().size(); j++) {
260 resources += dInfo.getResourceInfoList().get(j).getResourceName()
261 + " ";
262 }
263 if (url.toLowerCase().contains(filter)
264 || resources.toLowerCase().contains(filter)) {
265 visibleRows.add(Gate.getKnownPlugins().get(i));
266 }
267 }
268 }
269 if (!previousVisibleRows.equals(visibleRows)) {
270 mainTableModel.fireTableDataChanged();
271 }
272 if (mainTable.getRowCount() > 0) {
273 SwingUtilities.invokeLater(new Runnable() { public void run() {
274 mainTable.setRowSelectionInterval(0, 0);
275 if (filter.length() < 2
276 && previousURL != null
277 && !previousURL.equals("")) {
278 // reselect the last selected row based on its name and url values
279 for (int row = 0; row < mainTable.getRowCount(); row++) {
280 String url = (String) mainTable.getValueAt(
281 row, mainTable.convertColumnIndexToView(URL_COLUMN));
282 if (url.equals(previousURL)) {
283 mainTable.setRowSelectionInterval(row, row);
284 mainTable.scrollRectToVisible(
285 mainTable.getCellRect(row, 0, true));
286 break;
287 }
288 }
289 }
290 }});
291 }
292 }
293
294 protected Boolean getLoadNow(URL url){
295 Boolean res = loadNowByURL.get(url);
296 if(res == null){
297 res = Gate.getCreoleRegister().getDirectories().contains(url);
298 loadNowByURL.put(url, res);
299 }
300 return res;
301 }
302
303 protected Boolean getLoadAlways(URL url){
304 Boolean res = loadAlwaysByURL.get(url);
305 if(res == null){
306 res = Gate.getAutoloadPlugins().contains(url);
307 loadAlwaysByURL.put(url, res);
308 }
309 return res;
310 }
311
312 protected class MainTableModel extends AbstractTableModel{
313 public MainTableModel(){
314 localIcon = MainFrame.getIcon("open-file");
315 remoteIcon = MainFrame.getIcon("internet");
316 invalidIcon = MainFrame.getIcon("param");
317 }
318 public int getRowCount(){
319 return visibleRows.size();
320 }
321
322 public int getColumnCount(){
323 return 6;
324 }
325
326 public String getColumnName(int column){
327 switch (column){
328 case NAME_COLUMN: return "Name";
329 case ICON_COLUMN: return "";
330 case URL_COLUMN: return "URL";
331 case LOAD_NOW_COLUMN: return "Load now";
332 case LOAD_ALWAYS_COLUMN: return "Load always";
333 case DELETE_COLUMN: return "Delete";
334 default: return "?";
335 }
336 }
337
338 public Class getColumnClass(int columnIndex){
339 switch (columnIndex){
340 case NAME_COLUMN: return String.class;
341 case ICON_COLUMN: return Icon.class;
342 case URL_COLUMN: return String.class;
343 case LOAD_NOW_COLUMN: return Boolean.class;
344 case LOAD_ALWAYS_COLUMN: return Boolean.class;
345 case DELETE_COLUMN: return Object.class;
346 default: return Object.class;
347 }
348 }
349
350 public Object getValueAt(int row, int column){
351 Gate.DirectoryInfo dInfo = Gate.getDirectoryInfo(visibleRows.get(row));
352 if (dInfo == null) { return null; }
353 switch (column){
354 case NAME_COLUMN: return getName4URL(dInfo.getUrl());
355 case ICON_COLUMN: return
356 dInfo.isValid() ? (
357 dInfo.getUrl().getProtocol().equalsIgnoreCase("file") ?
358 localIcon : remoteIcon) :
359 invalidIcon;
360 case URL_COLUMN: return dInfo.getUrl().toString();
361 case LOAD_NOW_COLUMN: return getLoadNow(dInfo.getUrl());
362 case LOAD_ALWAYS_COLUMN: return getLoadAlways(dInfo.getUrl());
363 case DELETE_COLUMN: return null;
364 default: return null;
365 }
366 }
367
368 private String getName4URL(URL url) {
369 String path = "";
370 try {
371 path = url.toURI().getPath();
372 } catch (URISyntaxException ex) {
373 // ignore, this should have been checked when adding the URL!
374 }
375 if(path.endsWith("/")) {
376 path = path.substring(0,path.length()-1);
377 }
378 int lastSlash = path.lastIndexOf("/");
379 if(lastSlash == -1) {
380 return path;
381 } else {
382 return path.substring(lastSlash+1);
383 }
384 }
385
386 public boolean isCellEditable(int rowIndex, int columnIndex){
387 return columnIndex == LOAD_NOW_COLUMN ||
388 columnIndex == LOAD_ALWAYS_COLUMN ||
389 columnIndex == DELETE_COLUMN;
390 }
391
392 public void setValueAt(Object aValue, int rowIndex, int columnIndex){
393 Boolean valueBoolean = (Boolean)aValue;
394 Gate.DirectoryInfo dInfo =
395 Gate.getDirectoryInfo(visibleRows.get(rowIndex));
396 if (dInfo == null) { return; }
397 switch(columnIndex){
398 case LOAD_NOW_COLUMN:
399 loadNowByURL.put(dInfo.getUrl(), valueBoolean);
400 // for some reason the focus is sometime lost after editing
401 // however it is needed for Enter key to execute OkAction
402 mainTable.requestFocusInWindow();
403 break;
404 case LOAD_ALWAYS_COLUMN:
405 loadAlwaysByURL.put(dInfo.getUrl(), valueBoolean);
406 mainTable.requestFocusInWindow();
407 break;
408 }
409 }
410
411 protected Icon localIcon;
412 protected Icon remoteIcon;
413 protected Icon invalidIcon;
414 }
415
416 protected class ResourcesListModel extends AbstractListModel{
417
418 public Object getElementAt(int index){
419 int row = mainTable.getSelectedRow();
420 if(row == -1) return null;
421 row = mainTable.rowViewToModel(row);
422 Gate.DirectoryInfo dInfo = Gate.getDirectoryInfo(visibleRows.get(row));
423 return dInfo.getResourceInfoList().get(index);
424 }
425
426 public int getSize(){
427 int row = mainTable.getSelectedRow();
428 if(row == -1) return 0;
429 row = mainTable.rowViewToModel(row);
430 Gate.DirectoryInfo dInfo = Gate.getDirectoryInfo(visibleRows.get(row));
431 if (dInfo == null) { return 0; }
432 return dInfo.getResourceInfoList().size();
433 }
434
435 public void dataChanged(){
436 fireContentsChanged(this, 0, getSize() - 1);
437 }
438 }
439
440 /**
441 * This class acts both as cell renderer and editor for all the cells in the
442 * delete column.
443 */
444 protected class DeleteColumnCellRendererEditor extends AbstractCellEditor
445 implements TableCellRenderer, TableCellEditor{
446
447 public DeleteColumnCellRendererEditor(){
448 label = new JLabel();
449 rendererDeleteButton = new JButton(MainFrame.getIcon("delete"));
450 rendererDeleteButton.setMaximumSize(rendererDeleteButton.getPreferredSize());
451 rendererDeleteButton.setMargin(new Insets(2, 5, 2, 5));
452 rendererBox = new JPanel();
453 rendererBox.setLayout(new GridBagLayout());
454 rendererBox.setOpaque(false);
455 GridBagConstraints constraints = new GridBagConstraints();
456 constraints.fill = GridBagConstraints.NONE;
457 constraints.gridy = 0;
458 constraints.gridx = GridBagConstraints.RELATIVE;
459 constraints.weightx = 1;
460 rendererBox.add(Box.createGlue(), constraints);
461 constraints.weightx = 0;
462 rendererBox.add(rendererDeleteButton, constraints);
463 constraints.weightx = 1;
464 rendererBox.add(Box.createGlue(), constraints);
465
466 editorDeleteButton = new JButton(MainFrame.getIcon("delete"));
467 editorDeleteButton.setMargin(new Insets(2, 5, 2, 5));
468 editorDeleteButton.addActionListener(new ActionListener(){
469 public void actionPerformed(ActionEvent evt){
470 int row = mainTable.getEditingRow();
471 // tell Swing that we aren't really editing this cell, otherwise an
472 // exception occurs when Swing tries to stop editing a cell that has
473 // been deleted.
474 TableCellEditor currentEditor = mainTable.getCellEditor();
475 if(currentEditor != null) {
476 currentEditor.cancelCellEditing();
477 }
478 int rowModel = mainTable.rowViewToModel(row);
479 URL toDelete = visibleRows.get(rowModel);
480 Gate.removeKnownPlugin(toDelete);
481 loadAlwaysByURL.remove(toDelete);
482 loadNowByURL.remove(toDelete);
483 // redisplay the table with the current filter
484 filterRows(filterTextField.getText());
485 }
486 });
487 editorDeleteButton.setMaximumSize(editorDeleteButton.getPreferredSize());
488 editorBox = new JPanel();
489 editorBox.setLayout(new GridBagLayout());
490 editorBox.setOpaque(false);
491 constraints.weightx = 1;
492 editorBox.add(Box.createGlue(), constraints);
493 constraints.weightx = 0;
494 editorBox.add(editorDeleteButton, constraints);
495 constraints.weightx = 1;
496 editorBox.add(Box.createGlue(), constraints);
497 }
498
499 public Component getTableCellRendererComponent(JTable table,
500 Object value,
501 boolean isSelected,
502 boolean hasFocus,
503 int row,
504 int column){
505 switch(column){
506 case DELETE_COLUMN:
507 return rendererBox;
508 default: return null;
509 }
510 }
511
512 public Component getTableCellEditorComponent(JTable table,
513 Object value,
514 boolean isSelected,
515 int row,
516 int column){
517 switch(column){
518 case DELETE_COLUMN:
519 return editorBox;
520 default: return null;
521 }
522 }
523
524 public Object getCellEditorValue(){
525 return null;
526 }
527
528 JButton editorDeleteButton;
529 JButton rendererDeleteButton;
530 JPanel rendererBox;
531 JPanel editorBox;
532 JLabel label;
533 }
534
535 protected class IconTableCellRenderer extends DefaultTableCellRenderer{
536 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
537 if(value instanceof Icon){
538 super.getTableCellRendererComponent(table, "",
539 isSelected, hasFocus, row, column);
540 setIcon((Icon)value);
541 return this;
542 }else{
543 return super.getTableCellRendererComponent(table, value,
544 isSelected, hasFocus, row, column);
545 }
546 }
547
548 }
549
550 protected class ResourcesListCellRenderer extends DefaultListCellRenderer{
551 public Component getListCellRendererComponent(JList list, Object value,
552 int index, boolean isSelected, boolean cellHasFocus){
553 Gate.ResourceInfo rInfo = (Gate.ResourceInfo)value;
554 //prepare the renderer
555 String filter = filterTextField.getText().trim().toLowerCase();
556 if (filter.length() > 1
557 && rInfo.getResourceName().toLowerCase().contains(filter)) {
558 isSelected = true; // select resource if matching table row filter
559 }
560 super.getListCellRendererComponent(list, rInfo.getResourceName(),
561 index, isSelected, cellHasFocus);
562 //add tooltip text
563 setToolTipText(rInfo.getResourceComment());
564 return this;
565 }
566 }
567
568 protected class OkAction extends AbstractAction {
569 public OkAction(){
570 super("OK");
571 }
572 public void actionPerformed(ActionEvent evt){
573 setVisible(false);
574 //update the data structures to reflect the user's choices
575 Iterator pluginIter = loadNowByURL.keySet().iterator();
576 while(pluginIter.hasNext()){
577 URL aPluginURL = (URL)pluginIter.next();
578 boolean load = loadNowByURL.get(aPluginURL);
579 boolean loaded = Gate.getCreoleRegister().
580 getDirectories().contains(aPluginURL);
581 if(load && !loaded){
582 //load the directory
583 try{
584 Gate.getCreoleRegister().registerDirectories(aPluginURL);
585 }catch(GateException ge){
586 throw new GateRuntimeException(ge);
587 }
588 }
589 if(!load && loaded){
590 //remove the directory
591 Gate.getCreoleRegister().removeDirectory(aPluginURL);
592 }
593 }
594
595
596 pluginIter = loadAlwaysByURL.keySet().iterator();
597 while(pluginIter.hasNext()){
598 URL aPluginURL = (URL)pluginIter.next();
599 boolean load = loadAlwaysByURL.get(aPluginURL);
600 boolean loaded = Gate.getAutoloadPlugins().contains(aPluginURL);
601 if(load && !loaded){
602 //set autoload top true
603 Gate.addAutoloadPlugin(aPluginURL);
604 }
605 if(!load && loaded){
606 //set autoload to false
607 Gate.removeAutoloadPlugin(aPluginURL);
608 }
609 }
610 loadNowByURL.clear();
611 loadAlwaysByURL.clear();
612 }
613 }
614
615 /**
616 * Overridden so we can populate the UI before showing.
617 */
618 public void setVisible(boolean visible){
619 if(visible){
620 loadNowByURL.clear();
621 loadAlwaysByURL.clear();
622 mainTableModel.fireTableDataChanged();
623 if (mainTable.getRowCount() > 0) {
624 // select the first row
625 mainTable.setRowSelectionInterval(0, 0);
626 mainTable.scrollRectToVisible(
627 mainTable.getCellRect(0, 0, true));
628 }
629 } else {
630 // clear the filter
631 filterTextField.setText("");
632 }
633 super.setVisible(visible);
634 }
635
636 protected class CancelAction extends AbstractAction {
637 public CancelAction(){
638 super("Cancel");
639 }
640 public void actionPerformed(ActionEvent evt){
641 setVisible(false);
642 loadNowByURL.clear();
643 loadAlwaysByURL.clear();
644 }
645 }
646
647 protected class HelpAction extends AbstractAction {
648 public HelpAction() {
649 super("Help");
650 }
651 public void actionPerformed(ActionEvent evt) {
652 MainFrame.getInstance().showHelpFrame(
653 "sec:howto:plugins", "gate.gui.PluginManagerUI");
654 }
655 }
656
657 protected class AddCreoleRepositoryAction extends AbstractAction {
658 public AddCreoleRepositoryAction(){
659 super("Add a CREOLE repository",
660 MainFrame.getIcon("crystal-clear-action-edit-add.png"));
661 putValue(SHORT_DESCRIPTION,"Load a new CREOLE repository");
662 }
663
664 public void actionPerformed(ActionEvent e) {
665 Box messageBox = Box.createHorizontalBox();
666 Box leftBox = Box.createVerticalBox();
667 JTextField urlTextField = new JTextField(20);
668 leftBox.add(new JLabel("Type an URL"));
669 leftBox.add(urlTextField);
670 messageBox.add(leftBox);
671
672 messageBox.add(Box.createHorizontalStrut(10));
673 messageBox.add(new JLabel("or"));
674 messageBox.add(Box.createHorizontalStrut(10));
675
676 class URLfromFileAction extends AbstractAction{
677 URLfromFileAction(JTextField textField){
678 super(null, MainFrame.getIcon("open-file"));
679 putValue(SHORT_DESCRIPTION,"Click to select a directory");
680 this.textField = textField;
681 }
682
683 public void actionPerformed(ActionEvent e){
684 XJFileChooser fileChooser = MainFrame.getFileChooser();
685 fileChooser.setMultiSelectionEnabled(false);
686 fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
687 fileChooser.setFileFilter(fileChooser.getAcceptAllFileFilter());
688 fileChooser.setResource("gate.CreoleRegister");
689 int result = fileChooser.showOpenDialog(PluginManagerUI.this);
690 if(result == JFileChooser.APPROVE_OPTION){
691 try{
692 textField.setText(fileChooser.getSelectedFile().
693 toURI().toURL().toExternalForm());
694 }catch(MalformedURLException mue){
695 throw new GateRuntimeException(mue.toString());
696 }
697 }
698 }
699 JTextField textField;
700 } //class URLfromFileAction extends AbstractAction
701
702 Box rightBox = Box.createVerticalBox();
703 rightBox.add(new JLabel("Select a directory"));
704 JButton fileBtn = new JButton(new URLfromFileAction(urlTextField));
705 rightBox.add(fileBtn);
706 messageBox.add(rightBox);
707
708 int res = JOptionPane.showOptionDialog(PluginManagerUI.this, messageBox,
709 "Enter an URL to the directory containing the \"creole.xml\" file",
710 JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, null, null);
711 if(res == JOptionPane.OK_OPTION){
712 try{
713 final URL creoleURL = new URL(urlTextField.getText());
714 Gate.addKnownPlugin(creoleURL);
715 mainTable.clearSelection();
716 // redisplay the table without filtering
717 filterRows("");
718 // clear the filter text field
719 filterTextField.setText("");
720 // select the new plugin row
721 SwingUtilities.invokeLater(new Runnable() { public void run() {
722 for (int row = 0; row < mainTable.getRowCount(); row++) {
723 String url = (String) mainTable.getValueAt(
724 row, mainTable.convertColumnIndexToView(URL_COLUMN));
725 if (url.equals(creoleURL.toString())) {
726 mainTable.setRowSelectionInterval(row, row);
727 mainTable.scrollRectToVisible(
728 mainTable.getCellRect(row, 0, true));
729 break;
730 }
731 }
732 }});
733 mainTable.requestFocusInWindow();
734 }catch(Exception ex){
735 JOptionPane.showMessageDialog(
736 PluginManagerUI.this,
737 "There was a problem with your selection:\n" +
738 ex.toString() ,
739 "GATE", JOptionPane.ERROR_MESSAGE);
740 ex.printStackTrace(Err.getPrintWriter());
741 }
742 }
743 }
744 }//class LoadCreoleRepositoryAction extends AbstractAction
745
746 protected XJTable mainTable;
747 /** Contains the URLs from Gate.getKnownPlugins() that satisfy the filter
748 * filterTextField for the plugin URL and the plugin resources names */
749 protected List<URL> visibleRows;
750 protected JSplitPane mainSplit;
751 protected MainTableModel mainTableModel;
752 protected ResourcesListModel resourcesListModel;
753 protected JList resourcesList;
754 protected JTextField filterTextField;
755
756 /**
757 * Map from URL to Boolean. Stores temporary values for the loadNow options.
758 */
759 protected Map<URL, Boolean> loadNowByURL;
760 /**
761 * Map from URL to Boolean. Stores temporary values for the loadAlways
762 * options.
763 */
764 protected Map<URL, Boolean> loadAlwaysByURL;
765
766 protected static final int ICON_COLUMN = 0;
767 protected static final int NAME_COLUMN = 1;
768 protected static final int URL_COLUMN = 2;
769 protected static final int LOAD_NOW_COLUMN = 3;
770 protected static final int LOAD_ALWAYS_COLUMN = 4;
771 protected static final int DELETE_COLUMN = 5;
772 }
|