source: main/trunk/gli/src/org/greenstone/gatherer/cdm/ClassifierManager.java@ 22970

Last change on this file since 22970 was 22970, checked in by sjm84, 14 years ago

Added the ability to change the database type between GDBM, JDBM and SQLite

  • Property svn:keywords set to Author Date Id Revision
File size: 28.1 KB
Line 
1/**
2 *#########################################################################
3 *
4 * A component of the Gatherer application, part of the Greenstone digital
5 * library suite from the New Zealand Digital Library Project at the
6 * University of Waikato, New Zealand.
7 *
8 * Author: John Thompson, Greenstone Digital Library, University of Waikato
9 *
10 * Copyright (C) 1999 New Zealand Digital Library Project
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 *########################################################################
26 */
27package org.greenstone.gatherer.cdm;
28
29import java.awt.*;
30import java.awt.event.*;
31import java.io.*;
32import java.net.*;
33import java.util.*;
34import java.util.jar.*;
35import javax.swing.*;
36import javax.swing.event.*;
37import org.apache.xerces.parsers.*;
38import org.greenstone.gatherer.Configuration;
39import org.greenstone.gatherer.DebugStream;
40import org.greenstone.gatherer.Dictionary;
41import org.greenstone.gatherer.Gatherer;
42import org.greenstone.gatherer.greenstone.Classifiers;
43import org.greenstone.gatherer.gui.DesignPaneHeader;
44import org.greenstone.gatherer.gui.GComboBox;
45import org.greenstone.gatherer.gui.GLIButton;
46import org.greenstone.gatherer.util.JarTools;
47import org.greenstone.gatherer.util.StaticStrings;
48import org.greenstone.gatherer.util.Utility;
49import org.greenstone.gatherer.util.XMLTools;
50import org.w3c.dom.*;
51import org.xml.sax.*;
52
53/** This class is responsible for keeping track of all the classifiers assigned to this collection, and providing methods for adding and removing them.
54 * @author John Thompson, Greenstone Digital Library, University of Waikato
55 * @version 2.3
56 */
57public class ClassifierManager
58extends DOMProxyListModel {
59
60 private DatabaseTypeManager database_type_manager = null;
61 private String database_type = null;
62
63 /** The controls for editing the contents of this manager. */
64 private Control controls = null;
65
66 private DOMProxyListModel model;
67 private Classifier default_classifier = null;
68
69 /** Constructor.
70 * @see org.greenstone.gatherer.cdm.DynamicListModel
71 * @see org.greenstone.gatherer.collection.CollectionManager
72 */
73 public ClassifierManager () {
74 super (CollectionDesignManager.collect_config.getDocumentElement (), StaticStrings.CLASSIFY_ELEMENT, new Classifier ());
75 this.model = this;
76 DebugStream.println ("ClassifierManager: " + getSize () + " classifiers parsed.");
77
78 database_type_manager = new DatabaseTypeManager();
79 database_type = database_type_manager.getDatabaseType();
80
81 // Force the assigned classifiers to be loaded and cached now
82 for (int i = 0; i < getSize (); i++) {
83 getElementAt (i);
84 }
85 }
86
87
88 /** Retrieve a list of the classifiers that are available to be added to the collection. */
89 private Object[] getAvailableClassifiers () {
90 ArrayList available = new ArrayList ();
91
92 // Add all the non-abstract core Greenstone classifiers
93 ArrayList classifiers_list = Classifiers.getClassifiersList ();
94 for (int i = 0; i < classifiers_list.size (); i++) {
95 Classifier classifier = (Classifier) classifiers_list.get (i);
96 if (!classifier.isAbstract ()) {
97 available.add (classifier);
98 }
99 if (classifier.toString().equals("List")) {
100 default_classifier = classifier;
101 }
102 }
103
104 // Sort the available classifiers into alphabetical order
105 Collections.sort (available);
106
107 return available.toArray ();
108 }
109
110
111 /** Method to assign a classifier (i.e., add a new classifier onto the list).
112 * @param classifier The base <strong>Classifier</strong> to assign.
113 * @see org.greenstone.gatherer.cdm.DynamicListModel
114 */
115 private void assignClassifier (Classifier classifier) {
116 if(!contains (classifier)) {
117 Element element = classifier.getElement ();
118 // Locate where we should insert this new classifier.
119 Node target_node = CollectionConfiguration.findInsertionPoint (element);
120 add (root, classifier, target_node);
121
122 // tell the format manager to update the names of its format statements
123 Gatherer.c_man.getCollection ().cdm.format_manager.refresh ();
124 }
125 }
126
127
128 /** Destructor. */
129 public void destroy () {
130 if (controls != null) {
131 controls.destroy ();
132 controls = null;
133 }
134 }
135
136
137 /** Method to retrieve the classifier with the given index.
138 * @param index The index of the desired classifier as an <i>int</i>.
139 * @return The requested Classifier or <i>null</i> if no such classifier exists.
140 */
141 public Classifier getClassifier (int index) {
142 if(0 <= index && index < getSize ()) {
143 return (Classifier) getElementAt (index);
144 }
145 return null;
146 }
147
148 /** Method to retrieve the control for this manager.
149 * @return the Control for editing classifiers
150 */
151 public Control getControls () {
152 if(controls == null) {
153 // Build controls
154 this.controls = new ClassifierControl ();
155 }
156 return controls;
157 }
158
159 /** Called when the detail mode has changed which in turn may cause several design elements to be available/hidden
160 * @param mode the new mode as an int
161 */
162 public void modeChanged (int mode) {
163
164 }
165
166
167
168 /** Determine if the Phind classifier has been assigned.
169 * @return true if it has, false otherwise
170 */
171 public boolean isPhindClassifierAssigned () {
172 for(int i = 0; i < getSize (); i++) {
173 Classifier classifier = (Classifier) getElementAt (i);
174 if(classifier.getName ().equalsIgnoreCase (StaticStrings.PHIND_CLASSIFIER)) {
175 return true;
176 }
177 classifier = null;
178 }
179 return false;
180 }
181
182 /** Determine if a DateList classifier has been assigned
183 * @return true if it has, false otherwise
184 */
185 public boolean isDateListClassifierAssigned () {
186 for(int i = 0; i < getSize (); i++) {
187 Classifier classifier = (Classifier) getElementAt (i);
188 if(classifier.getName ().equalsIgnoreCase (StaticStrings.DATELIST_CLASSIFIER)) {
189 return true;
190 }
191 classifier = null;
192 }
193 return false;
194
195 }
196 /** Method to move a classifier in the list order.
197 * @param classifier the Classifier you want to move.
198 * @param direction true to move the classifier up, false to move it down.
199 * @param all true to move to move all the way, false for a single step.
200 */
201 private void moveClassifier (Classifier classifier, boolean direction, boolean all) {
202 if(getSize () < 2) {
203 DebugStream.println ("Not enough classifiers to allow moving.");
204 return;
205 }
206 if(all) {
207 // Move to top
208 if(direction) {
209 // Remove the moving classifier
210 remove (classifier);
211 // Retrieve the first classifier
212 Classifier first_classifier = (Classifier) getElementAt (0);
213 // Add the moving classifier before the first classifier
214 addBefore (classifier, first_classifier);
215 first_classifier = null;
216 }
217 else {
218 // Remove the moving classifier
219 remove (classifier);
220 // And add after last classifier
221 add (getSize (), classifier);
222 }
223 }
224 else {
225 // Try to move the classifier one step in the desired direction.
226 int index = indexOf (classifier);
227 ///ystem.err.println("Index of " + classifier + " = " + index);
228 if(direction) {
229 index--;
230 if(index < 0) {
231 String args[] = new String[2];
232 args[0] = Dictionary.get ("CDM.ClassifierManager.Classifier");
233 args[1] = classifier.getName ();
234 JOptionPane.showMessageDialog (Gatherer.g_man, Dictionary.get ("CDM.Move.At_Top", args), Dictionary.get ("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE);
235 return;
236 }
237 remove (classifier);
238 add (index, classifier);
239 }
240 else {
241 index++;
242 if(index >= getSize ()) {
243 String args[] = new String[2];
244 args[0] = Dictionary.get ("CDM.ClassifierManager.Classifier_Str");
245 args[1] = classifier.getName ();
246 JOptionPane.showMessageDialog (Gatherer.g_man, Dictionary.get ("CDM.Move.At_Bottom", args), Dictionary.get ("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE);
247 return;
248 }
249 remove (classifier);
250 add (index, classifier);
251 }
252 }
253
254 // tell the format manager to update the names of its format statements
255 Gatherer.c_man.getCollection ().cdm.format_manager.refresh ();
256 }
257
258 /** This method removes an assigned classifier. I was tempted to call it unassign, but remove is more consistant. Note that there is no way to remove a classifier from the library.
259 * @param classifier The Classifier to remove
260 * @see org.greenstone.gatherer.cdm.DynamicListModel
261 */
262 private void removeClassifier (Classifier classifier) {
263 remove (classifier);
264 // tell the format manager to update the names of its format statements
265 Gatherer.c_man.getCollection ().cdm.format_manager.refresh ();
266
267 }
268 // When remove, move, and add(assign) classifiers, this method has to be called to get the feature combobox
269 // on the 'format feature' panel of the 'format' panel up to date.
270// private void informFormatManager() {
271// //this is really to call the gainFocus() method
272// CollectionDesignManager.format_manager.getControls();
273// }
274
275 /** A class which provides controls for assigned and editing classifiers. */
276 private class ClassifierControl
277 extends JPanel
278 implements Control, DatabaseTypeManager.DatabaseTypeListener {
279 /** A combobox containing all of the known classifiers, including those that may have already been assigned. */
280 private JComboBox classifier_combobox = null;
281 /** Button for adding classifiers. */
282 private JButton add = null;
283 /** Button for configuring the selected classifier. */
284 private JButton configure = null;
285 private JButton move_down_button;
286 private JButton move_up_button;
287
288 /** Button to remove the selected classifier. */
289 private JButton remove = null;
290
291 private JPanel database_type_panel = (JPanel)database_type_manager.getControls();
292
293 /** A list of assigned classifiers. */
294 private JList classifier_list = null;
295
296 /** Constructor.
297 * @see org.greenstone.gatherer.cdm.ClassifierManager.ClassifierControl.AddListener
298 * @see org.greenstone.gatherer.cdm.ClassifierManager.ClassifierControl.ConfigureListener
299 * @see org.greenstone.gatherer.cdm.ClassifierManager.ClassifierControl.RemoveListener
300 */
301 public ClassifierControl () {
302 // Create
303 this.setComponentOrientation(Dictionary.getOrientation());
304 add = new GLIButton (Dictionary.get ("CDM.ClassifierManager.Add"), Dictionary.get ("CDM.ClassifierManager.Add_Tooltip"));
305
306 JPanel button_pane = new JPanel ();
307 button_pane.setComponentOrientation(Dictionary.getOrientation());
308 JPanel central_pane = new JPanel ();
309 central_pane.setComponentOrientation(Dictionary.getOrientation());
310
311 configure = new GLIButton (Dictionary.get ("CDM.ClassifierManager.Configure"), Dictionary.get ("CDM.ClassifierManager.Configure_Tooltip"));
312 configure.setEnabled (false);
313
314 JPanel header_pane = new DesignPaneHeader ("CDM.GUI.Classifiers", "classifiers");
315
316 ClassifierComboboxListener ccl = new ClassifierComboboxListener ();
317 classifier_combobox = new JComboBox (getAvailableClassifiers ());
318 classifier_combobox.setComponentOrientation(Dictionary.getOrientation());
319 classifier_combobox.setOpaque (!Utility.isMac ());
320 classifier_combobox.setEditable (false);
321 if(classifier_combobox.getItemCount () > 0) {
322 if (default_classifier!=null) {
323 classifier_combobox.setSelectedItem(default_classifier);
324 } else {
325 classifier_combobox.setSelectedIndex (0);
326 }
327 ccl.itemStateChanged (new ItemEvent (classifier_combobox, 0, null, ItemEvent.SELECTED));
328 }
329
330 JLabel classifier_label = new JLabel (Dictionary.get ("CDM.ClassifierManager.Classifier"));
331 classifier_label.setComponentOrientation(Dictionary.getOrientation());
332
333 classifier_list = new JList (model);
334 classifier_list.setComponentOrientation(Dictionary.getOrientation());
335
336 classifier_list.setOpaque (true);
337 classifier_list.setSelectionMode (ListSelectionModel.SINGLE_SELECTION);
338 JLabel classifier_list_label = new JLabel (Dictionary.get ("CDM.ClassifierManager.Assigned"));
339 classifier_list_label.setComponentOrientation(Dictionary.getOrientation());
340
341 classifier_list_label.setOpaque (true);
342
343 JPanel classifier_list_pane = new JPanel ();
344 classifier_list_pane.setComponentOrientation(Dictionary.getOrientation());
345
346 JPanel classifier_pane = new JPanel ();
347 classifier_pane.setComponentOrientation(Dictionary.getOrientation());
348 remove = new GLIButton (Dictionary.get ("CDM.ClassifierManager.Remove"), Dictionary.get ("CDM.ClassifierManager.Remove_Tooltip"));
349 remove.setEnabled (false);
350
351 JPanel temp = new JPanel (new BorderLayout ());
352 temp.setComponentOrientation(Dictionary.getOrientation());
353
354 JPanel move_button_pane = new JPanel ();
355 move_button_pane.setComponentOrientation(Dictionary.getOrientation());
356
357 move_up_button = new GLIButton (Dictionary.get ("CDM.Move.Move_Up"), JarTools.getImage ("arrow-up.gif"), Dictionary.get ("CDM.Move.Move_Up_Tooltip"));
358 move_up_button.setEnabled (false);
359
360 move_down_button = new GLIButton (Dictionary.get ("CDM.Move.Move_Down"), JarTools.getImage ("arrow-down.gif"), Dictionary.get ("CDM.Move.Move_Down_Tooltip"));
361 move_down_button.setEnabled (false);
362
363 // Listeners
364 add.addActionListener (new AddListener ());
365 classifier_combobox.addItemListener (ccl);
366 configure.addActionListener (new ConfigureListener ());
367 remove.addActionListener (new RemoveListener ());
368 remove.addActionListener (CollectionDesignManager.buildcol_change_listener);
369 classifier_list.addMouseListener (new ClickListener ());
370 classifier_list.addListSelectionListener (new ListListener ());
371 ccl = null;
372
373 MoveListener ml = new MoveListener ();
374 move_down_button.addActionListener (ml);
375 move_down_button.addActionListener (CollectionDesignManager.buildcol_change_listener);
376 move_up_button.addActionListener (ml);
377 move_up_button.addActionListener (CollectionDesignManager.buildcol_change_listener);
378
379 // Layout
380 JPanel tmp;
381 move_button_pane.setLayout (new GridLayout (4,1));
382 move_button_pane.add (move_up_button);
383 tmp = new JPanel ();
384 tmp.setComponentOrientation(Dictionary.getOrientation());
385 move_button_pane.add (tmp);
386 tmp = new JPanel ();
387 tmp.setComponentOrientation(Dictionary.getOrientation());
388 move_button_pane.add (tmp);
389 move_button_pane.add (move_down_button);
390
391 classifier_list_label.setBorder (BorderFactory.createEmptyBorder (0,2,0,2));
392
393 classifier_list_pane.setLayout (new BorderLayout ());
394 classifier_list_pane.add (classifier_list_label, BorderLayout.NORTH);
395 classifier_list_pane.add (new JScrollPane (classifier_list), BorderLayout.CENTER);
396 classifier_list_pane.add (move_button_pane, BorderLayout.LINE_END);
397
398 classifier_label.setBorder (BorderFactory.createEmptyBorder (0,0,5,0));
399
400 classifier_pane.setBorder (BorderFactory.createEmptyBorder (5,0,5,0));
401 classifier_pane.setLayout (new BorderLayout (5,0));
402 classifier_pane.add (classifier_label, BorderLayout.LINE_START);
403 classifier_pane.add (classifier_combobox, BorderLayout.CENTER);
404
405 button_pane.setLayout (new GridLayout (1, 3));
406 button_pane.add (add);
407 button_pane.add (configure);
408 button_pane.add (remove);
409
410 temp.add (classifier_pane, BorderLayout.NORTH);
411 temp.add (button_pane, BorderLayout.SOUTH);
412
413 central_pane.setBorder (BorderFactory.createEmptyBorder (5,0,0,0));
414 central_pane.setLayout (new BorderLayout ());
415 central_pane.add (database_type_panel, BorderLayout.NORTH);
416 central_pane.add (classifier_list_pane, BorderLayout.CENTER);
417 central_pane.add (temp, BorderLayout.SOUTH);
418
419 setBorder (BorderFactory.createEmptyBorder (0,5,0,0));
420 setLayout (new BorderLayout ());
421 add (header_pane, BorderLayout.NORTH);
422 add (central_pane, BorderLayout.CENTER);
423 }
424
425 /** Method which acts like a destructor, tidying up references to persistant objects.
426 */
427 public void destroy () {
428 add = null;
429 classifier_combobox = null;
430 classifier_list = null;
431 configure = null;
432 //instructions = null;
433 remove = null;
434 }
435
436 public void gainFocus () {
437 }
438
439 public void loseFocus () {
440 }
441
442
443 public void databaseTypeChanged(String new_database_type)
444 {
445 if(database_type.equals(new_database_type)){
446 return;
447 }
448 database_type = new_database_type;
449 }
450
451 private class AddListener
452 implements ActionListener {
453 public void actionPerformed (ActionEvent event) {
454 if (classifier_combobox.getSelectedItem () != null) {
455 // This must be done on a new thread for the remote building code
456 new AddClassifierTask (classifier_combobox.getSelectedItem ().toString ()).start ();
457 }
458 }
459 }
460
461
462 private class AddClassifierTask
463 extends Thread {
464 private String classifier_name;
465
466 public AddClassifierTask (String classifier_name) {
467 this.classifier_name = classifier_name;
468 }
469
470 public void run () {
471 // Retrieve the classifier
472 Classifier classifier = Classifiers.getClassifier (classifier_name, true);
473 if (classifier == null) {
474 System.err.println ("Error: getClassifier() returned null.");
475 return;
476 }
477
478 // Create a new element in the DOM
479 Element new_classifier_element = CollectionConfiguration.createElement (StaticStrings.CLASSIFY_ELEMENT);
480 new_classifier_element.setAttribute (StaticStrings.TYPE_ATTRIBUTE, classifier.getName ());
481
482 Classifier new_classifier = new Classifier (new_classifier_element, classifier);
483
484 ArgumentConfiguration ac = new ArgumentConfiguration (new_classifier);
485 ac.addOKButtonActionListener (CollectionDesignManager.buildcol_change_listener);
486 if (ac.display ()) {
487 assignClassifier (new_classifier);
488 classifier_list.setSelectedValue (new_classifier, true);
489 }
490 }
491 }
492
493
494 /** This listener reacts to changes in the current selection of the classifier combobox. */
495 private class ClassifierComboboxListener
496 implements ItemListener {
497 /** When a user selects a certain classifier, update the tooltip to show the classifier description. */
498 public void itemStateChanged (ItemEvent event) {
499 if(event.getStateChange () == ItemEvent.SELECTED) {
500 // Retrieve the selected classifier
501 Classifier current_selection = (Classifier) classifier_combobox.getSelectedItem ();
502 // And reset the tooltip.
503 classifier_combobox.setToolTipText (Utility.formatHTMLWidth (current_selection.getDescription (), 40));
504 current_selection = null;
505 }
506 }
507 }
508
509
510 /** Listens for double clicks apon the list and react as if the configure button was pushed. */
511 private class ClickListener
512 extends MouseAdapter {
513 /** Called whenever the mouse is clicked over a registered component, we use this to chain through to the configure prompt.
514 * @param event A <strong>MouseEvent</strong> containing information about the mouse click.
515 */
516 public void mouseClicked (MouseEvent event) {
517 if(event.getClickCount () == 2 ) {
518 if(!classifier_list.isSelectionEmpty ()) {
519 Classifier classifier = (Classifier) classifier_list.getSelectedValue ();
520 ArgumentConfiguration ac = new ArgumentConfiguration (classifier);
521 ac.addOKButtonActionListener (CollectionDesignManager.buildcol_change_listener);
522 if (ac.display ()) {
523 refresh (classifier);
524 }
525 ac.destroy ();
526 ac = null;
527 }
528 }
529 }
530 }
531
532 /** This class listens for actions upon the configure button in the controls, and if detected creates a new ArgumentConfiguration dialog box to allow for configuration.
533 */
534 private class ConfigureListener
535 implements ActionListener {
536 /** 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.
537 * @param event An <strong>ActionEvent</strong> containing information garnered from the control action.
538 * @see org.greenstone.gatherer.cdm.ArgumentConfiguration
539 * @see org.greenstone.gatherer.cdm.Classifier
540 */
541 public void actionPerformed (ActionEvent event) {
542 if(!classifier_list.isSelectionEmpty ()) {
543 Classifier classifier = (Classifier) classifier_list.getSelectedValue ();
544 ArgumentConfiguration ac = new ArgumentConfiguration (classifier);
545 ac.addOKButtonActionListener (CollectionDesignManager.buildcol_change_listener);
546 if (ac.display ()) {
547 refresh (classifier);
548 }
549 ac.destroy ();
550 ac = null;
551 }
552 }
553 }
554
555 /** 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 */
556 private class ListListener
557 implements ListSelectionListener {
558
559 public void valueChanged (ListSelectionEvent e) {
560 if (!e.getValueIsAdjusting ()) { // we get two events for one change in list selection - use the false one ( the second one)
561 if (classifier_list.isSelectionEmpty ()) {
562 move_up_button.setEnabled (false);
563 move_down_button.setEnabled (false);
564 configure.setEnabled (false);
565 remove.setEnabled (false);
566 }
567 else {
568 configure.setEnabled (true);
569 remove.setEnabled (true);
570 int selected_index = classifier_list.getSelectedIndex ();
571 move_up_button.setEnabled (selected_index !=0);
572 move_down_button.setEnabled (selected_index != model.getSize ()-1);
573 }
574 }
575 }
576 }
577
578 /** Listens for actions apon the move buttons in the manager controls, and if detected calls the <i>moveClassifier()</i> method of the manager with the appropriate details. */
579 private class MoveListener
580 implements ActionListener {
581 /** 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.
582 * @param event An <strong>ActionEvent</strong> containing information garnered from the control action.
583 */
584 public void actionPerformed (ActionEvent event) {
585 if(!classifier_list.isSelectionEmpty ()) {
586 Object object = classifier_list.getSelectedValue ();
587 if(object instanceof Classifier) {
588 Classifier classifier = (Classifier) object;
589 if(event.getSource () == move_up_button) {
590 moveClassifier (classifier, true, false);
591 }
592 else if(event.getSource () == move_down_button) {
593 moveClassifier (classifier, false, false);
594 }
595 classifier_list.setSelectedValue (classifier, true);
596 }
597 }
598 }
599 }
600
601 /** This class listens for actions upon the remove button in the controls, and if detected calls the <i>removeClassifier()</i> method.
602 */
603 private class RemoveListener
604 implements ActionListener {
605 /** 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.
606 * @param event An <strong>ActionEvent</strong> containing information garnered from the control action.
607 */
608 public void actionPerformed (ActionEvent event) {
609 if(classifier_list.isSelectionEmpty ()) {
610 remove.setEnabled (false);
611 return;
612 }
613 int selected_index = classifier_list.getSelectedIndex ();
614 Object selected_classifier = classifier_list.getSelectedValue ();
615 if (!(selected_classifier instanceof Classifier)) {
616 return; // what else could we have here???
617 }
618 removeClassifier ((Classifier)selected_classifier);
619
620 if (selected_index >= classifier_list.getModel ().getSize ()) {
621 selected_index--;
622 }
623 if (selected_index >=0) {
624 classifier_list.setSelectedIndex (selected_index);
625 } else {
626 // no more classifiers in the list
627 remove.setEnabled (false);
628 }
629 }
630 }
631 }
632}
Note: See TracBrowser for help on using the repository browser.