source: main/trunk/gli/src/org/greenstone/gatherer/feedback/CompListener.java@ 33998

Last change on this file since 33998 was 33998, checked in by davidb, 4 years ago

Removed import statement that is no longer used, and was stopping compilation using JDK11

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 22.4 KB
Line 
1package org.greenstone.gatherer.feedback;
2
3import java.awt.*;
4import java.io.*;
5import java.util.*;
6import javax.swing.*;
7import javax.swing.tree.*;
8import javax.swing.table.*;
9import javax.swing.text.*;
10import java.awt.image.*;
11import javax.imageio.ImageIO;
12import javax.swing.plaf.*;
13import javax.swing.plaf.basic.*;
14import javax.swing.colorchooser.*;
15import java.awt.event.*;
16import javax.swing.event.*;
17import java.text.MessageFormat;
18import javax.swing.plaf.metal.MetalIconFactory.*;
19import javax.swing.plaf.metal.MetalIconFactory;
20import javax.swing.plaf.basic.BasicInternalFrameTitlePane;
21import javax.swing.plaf.metal.MetalInternalFrameTitlePane;
22
23/**
24 * In general, this class will get add special listener
25 * to a Container and of all the components inside it.
26 * <p>This class will also add special listener to the Container and each of the components inside
27 * the Container. So, it will allows special listener to record and listen each of the actions
28 * the user do to the Container or any of the components inside it. The special listener
29 * is an instance of ActionRecorderDialog.</p>
30 * <p>This class will only recognized all the components that is belongs to the javax.swing package
31 * which are all the implementing classes of RootPaneContainer interface and all the direct known
32 * subclasses of JComponent. All the other components will be stated simply as Container
33 * and user cannot really get much information out of it.</p>
34 * <p>The added special listener to this component is as what its allowed in API, if the component
35 * have some modified listener added to it then that action will not be known and recorded by
36 * the special listener.</p>
37 *
38 * @author Veronica Liesaputra
39 */
40public class CompListener
41{
42 /**
43 * This variable will hold the special listener that will listen and record any of the
44 * actions user do to the Container and any of the components inside it.
45 */
46 private ActionRecorderDialog m;
47
48 /**
49 * This variable will hold the pair of the component and the model of the component.
50 * With this variable allows ActionRecorderDialog listener to know which component the model that fires an action
51 * belongs to. In this HashMap the model is the key and the component where the model belongs to is
52 * the value.
53 */
54 private HashMap hash;
55
56 /**
57 * This constructor will set the special listener, the locale and the hashmap to be used in
58 * this Container.
59 * (Precondition: dialog != null)
60 * @param dialog its the special listener that will listen and record all the action
61 * user do to any of the component inside the Container.
62 * @param h its the HashMap that will hold the pair of model with the component it belongs.
63 */
64 public CompListener
65 (ActionRecorderDialog dialog,HashMap h)
66 {
67 m = dialog;
68 hash = h;
69 }
70
71 /**
72 * If the JTextComponent is a JTextField then it will add the special action listener to it.
73 * (Precondition: txt != null)
74 * @param txt its the JTextComponent we want to get all the information from.
75 */
76 public void getTextAreaInfo(JTextComponent txt)
77 {
78 if (txt instanceof JTextField)
79 {
80 ((JTextField)txt).removeActionListener(m);
81 ((JTextField)txt).addActionListener(m);
82 }
83 }
84
85 /**
86 * This method will add the special action listener to the JButton.
87 * (Precondition: button != null)
88 * @param button its the JButton we want to get the information from.
89 */
90 public void getButtonInfo (JButton button)
91 {
92 button.removeActionListener(m);
93 button.addActionListener(m);
94 }
95
96 /**
97 * This method will get add the special change listener to the JProgressBar.
98 * (Precondition: bar != null)
99 * @param bar its the JProgressBar we want to get information from.
100 */
101 public void getProgressBarInfo (JProgressBar bar)
102 {
103 bar.removeChangeListener(m);
104 bar.addChangeListener(m);
105 }
106
107 /**
108 * This method will add the special change listener to the JSlider.
109 * (Precondition: slider != null)
110 * @param slider its the JSlider we want to get information from.
111 */
112 public void getSliderInfo (JSlider slider)
113 {
114 slider.removeChangeListener(m);
115 slider.addChangeListener(m);
116 }
117
118 /**
119 * This method will add the special change listener to the JSpinner.
120 * (Precondition: spinner != null)
121 * @param spinner its the JSpinner we want to the information from.
122 */
123 public void getSpinnerInfo (JSpinner spinner)
124 {
125 spinner.removeChangeListener(m);
126 spinner.addChangeListener(m);
127 }
128
129 /**
130 * Dummy method to get JLabel.
131 */
132 public void getLabelInfo(JLabel lbl)
133 {}
134
135 /**
136 * This method will add the special action listener to the JComboBox.
137 * (Precondition: box != null)
138 * @param box its the JComboBox we want to get information from.
139 */
140 public void getComboBoxInfo(JComboBox box)
141 {
142 ComboBoxModel cm;
143 cm = box.getModel();
144
145 box.removeActionListener(m);
146 box.addActionListener(m);
147 }
148
149 /**
150 * This method will add the special action listener to the JToggleButton.
151 * (Precondition: button != null)
152 * @param button its a JToggleButton inside the window.
153 */
154 public void getToggleButtonInfo (JToggleButton button)
155 {
156 button.removeActionListener(m);
157 button.addActionListener(m);
158 }
159
160 /**
161 * This method will add the special action listener to the JMenuItem.
162 * (Precondition: menuitem != null)
163 * @param menuitem its the JMenuItem we want to get the information from.
164 */
165 public void getMenuItemInfo (JMenuItem menuitem)
166 {
167 menuitem.removeActionListener(m);
168 menuitem.addActionListener(m);
169 }
170
171 /**
172 * This method will get all the components inside JMenuBar.
173 * (Precondition: menubar != null)
174 * @param menubar its the JMenuBar we want to get the information from.
175 */
176 public void getMenuBarInfo (JMenuBar menubar)
177 {
178 int i;
179 for (i= 0 ; i < menubar.getMenuCount() ; i++)
180 {
181 getInside(menubar.getMenu(i));
182 }
183 }
184
185 /**
186 * This method will add the special action and menu listener to the JMenu and
187 * get the components inside JMenu.
188 * (Precondition: menu != null)
189 * @param menu its the JMenu we want to the the information from.
190 */
191 public void getMenuInfo (JMenu menu)
192 {
193 menu.removeActionListener(m);
194 menu.removeMenuListener(m);
195 menu.addActionListener(m);
196 menu.addMenuListener(m);
197
198 int i;
199 for (i= 0 ; i < menu.getMenuComponentCount() ; i++)
200 {
201 getInside((Container)menu.getMenuComponent(i));
202 }
203 }
204
205 /**
206 * This method will get all the components inside the JApplet.
207 * (Precondition: applet != null)
208 * @param applet its the JApplet we want to get the information from.
209 */
210 public void getAppletInfo (JApplet applet)
211 {
212 Component[] group;
213 group = applet.getComponents();
214 int i;
215
216 if (group != null)
217 {
218 for (i = 0; i < group.length ; i++)
219 {
220 getInside((Container)applet.getComponent(i));
221 }
222 }
223 }
224
225 /**
226 * This method will get all the components inside the JWindow.
227 * (Precondition: window != null)
228 * @param window its the JWindow we want to get the information from.
229 */
230 public void getWindowInfo (JWindow window)
231 {
232 Component[] group;
233 group = window.getComponents();
234 int i;
235
236 if (group != null)
237 {
238 for (i = 0; i < group.length ; i++)
239 {
240 getInside((Container)window.getComponent(i));
241 }
242 }
243 }
244
245 /**
246 * This method will get all the components inside the JDialog.
247 * (Precondition: dialog != null)
248 * @param dialog its the JDialog we want to get the information from.
249 */
250 public void getDialogInfo (JDialog dialog)
251 {
252 Component[] group;
253 group = dialog.getComponents();
254 int i;
255
256 if (group != null)
257 {
258 for (i = 0; i < group.length ; i++)
259 {
260 getInside((Container)dialog.getComponent(i));
261 }
262 }
263 }
264
265 /**
266 * This method will get all the components inside the JInternalFrame.
267 * (Precondition: frame != null)
268 * @param frame its the JInternalFrame we want to get the information from.
269 */
270 public void getInternalFrameInfo (JInternalFrame frame)
271 {
272 Component[] group;
273 group = frame.getComponents();
274 int i;
275
276 if (group != null)
277 {
278 for (i = 0; i < group.length ; i++)
279 {
280 getInside((Container)frame.getComponent(i));
281 }
282 }
283 }
284
285 /**
286 * This method will get all the components inside the JFrame.
287 * (Precondition: frame != null)
288 * @param frame its the JFrame we want to get the information from.
289 */
290 public void getFrameInfo (JFrame frame)
291 {
292 Component[] group;
293 group = frame.getComponents();
294 int i;
295
296 if (group != null)
297 {
298 for (i = 0; i < group.length ; i++)
299 {
300 getInside((Container)frame.getComponent(i));
301 }
302 }
303 }
304
305 /**
306 * This method will get all the components inside the JPanel.
307 * (Precondition: pane != null)
308 * @param pane its the JPanel we want to get the information from.
309 */
310 public void getPanelInfo (JPanel pane)
311 {
312 Component[] group;
313 group = pane.getComponents();
314 int i;
315
316 if (group != null)
317 {
318 for (i = 0; i < group.length ; i++)
319 {
320 getInside((Container)pane.getComponent(i));
321 }
322 }
323 }
324
325 /**
326 * This method will get all the components inside the JScrollPane.
327 * (Precondition: scroll != null)
328 * @param scroll its the JScrollPane we want to get the information from.
329 */
330 public void getScrollInfo (JScrollPane scroll)
331 {
332 Component[] group;
333 group = scroll.getComponents();
334 int i;
335
336 if (group != null)
337 {
338 for (i = 0; i < group.length ; i++)
339 {
340 getInside((Container)group[i]);
341 }
342 }
343 }
344
345 /**
346 * This method will add special change listener to the JTabbedPane and get all
347 * the components inside it.
348 * (Precondition: tab != null)
349 * @param tab its the JTabbedPane we want to get the information from.
350 */
351 public void getTabbedPaneInfo (JTabbedPane tab)
352 {
353 int j;
354
355 tab.removeChangeListener(m);
356 tab.addChangeListener(m);
357
358 for (j = 0 ; j < tab.getTabCount(); j++)
359 {
360
361 Component group = tab.getComponentAt(j);
362 getInside((Container)group);
363
364 }
365 }
366
367 /**
368 * This is the dummy method to ge the option pane info.
369 */
370 public void getOptionPaneInfo (JOptionPane op)
371 {}
372
373 /**
374 * This method will get components inside the JViewPort.
375 * (Precondition: vp != null)
376 * @param vp its the JViewPort we want to get the information from.
377 */
378 public void getViewPortInfo (JViewport vp)
379 {
380 Component[] group;
381 group = vp.getComponents();
382 int i;
383
384 if (group != null)
385 {
386 for (i = 0; i < group.length ; i++)
387 {
388 getInside((Container)group[i]);
389 }
390 }
391 }
392
393 /**
394 * This method will get components inside the Box.
395 * (Precondition: box != null)
396 * @param box its the Box we want to get the information from.
397 */
398 public void getBoxInfo (Box box)
399 {
400 Component[] group;
401 group = box.getComponents();
402 int i;
403
404 if (group != null)
405 {
406 for (i = 0; i < group.length ; i++)
407 {
408 getInside((Container)group[i]);
409 }
410 }
411 }
412
413 /**
414 * This method will get components inside the JSplitPane.
415 * (Precondition: split != null)
416 * @param split its the JSplitPane we want to get the information from.
417 */
418 public void getSplitPaneInfo (JSplitPane split)
419 {
420 Component[] group;
421 group = split.getComponents();
422 int i;
423
424 if (group != null)
425 {
426 for (i = 0; i < group.length ; i++)
427 {
428 getInside((Container)group[i]);
429 }
430 }
431 }
432
433 /**
434 * This method will get add special list selection listener to the JList.
435 * (Precondition: list != null)
436 * @param list its the JList we want to get the information from.
437 */
438 public void getListInfo (JList list)
439 {
440 ListModel ls;
441 ls = list.getModel();
442
443 list.removeListSelectionListener(m);
444 list.addListSelectionListener(m);
445
446 if (ls != null)
447 {
448 if (hash.containsKey(ls) == false)
449 hash.put(ls,list);
450 ls.removeListDataListener(m);
451 ls.addListDataListener(m);
452 }
453 }
454
455 /**
456 * This method will add special change listener to the JColorChooser.
457 * (Precondition: color != null)
458 * @param color its the JColorChooser we want to get the information from.
459 */
460 public void getColorInfo (JColorChooser color)
461 {
462 ColorSelectionModel cm;
463 cm = color.getSelectionModel();
464
465 if (cm != null)
466 {
467 if (hash.containsKey(cm) == false)
468 hash.put(cm,color);
469 cm.removeChangeListener(m);
470 cm.addChangeListener(m);
471 }
472
473 getInside((Container) color.getPreviewPanel());
474 }
475
476 /**
477 * This method will add special action listener to the JFileChooser.
478 * (Precondition: fc != null)
479 * @param fc its the JFileChooser we want to get the information from.
480 */
481 public void getFileChooserInfo (JFileChooser fc)
482 {
483 fc.removeActionListener(m);
484 fc.addActionListener(m);
485 }
486
487 /**
488 * This method will add special list selection and column model listener
489 * to the JTable.
490 * (Precondition: table != null)
491 * @param table its the JTable we want to get the information from.
492 */
493 public void getTableInfo (JTable table)
494 {
495 TableModel tm;
496 tm = table.getModel();
497
498 TableColumnModel tcm;
499 tcm = table.getColumnModel();
500 ListSelectionModel lm;
501 lm = table.getSelectionModel();
502
503 if (lm != null)
504 {
505 if (hash.containsKey(lm) == false)
506 hash.put(lm,table);
507 lm.removeListSelectionListener(m);
508 lm.addListSelectionListener(m);
509 }
510
511 if (tcm != null)
512 {
513 if (hash.containsKey(tcm) == false)
514 hash.put(tcm,table);
515 tcm.removeColumnModelListener(m);
516 tcm.addColumnModelListener(m);
517 }
518 }
519
520 /**
521 * This is a dummy method to get the JScrollBar.
522 */
523 public void getScrollBarInfo (JScrollBar scroll)
524 {
525 }
526
527 /**
528 * This method will add special tree selection listener to the JTree.
529 * (Precondition: tree != null)
530 * @param tree its the JTree we want to get the information from.
531 */
532 public void getTreeInfo (JTree tree)
533 {
534 TreeModel tm;
535 tm = tree.getModel();
536
537 tree.removeTreeSelectionListener(m);
538 tree.addTreeSelectionListener(m);
539
540 if (tm != null)
541 {
542 if (hash.containsKey(tm) == false)
543 hash.put(tm,tree);
544 tm.removeTreeModelListener(m);
545 tm.addTreeModelListener(m);
546 }
547 }
548
549 /**
550 * This method is a dummy method to get Container.
551 */
552 public void getCompInfo (Container pane)
553 {
554 }
555
556 /**
557 * This method will get all components inside the JPopupMenu.
558 * (Precondition: popup != null)
559 * @param popup its the JPopUpMenu we want to get the information from.
560 */
561 public void getPopUpMenuInfo (JPopupMenu popup)
562 {
563 Component[] group;
564 group = popup.getComponents();
565 SingleSelectionModel sm;
566 sm = popup.getSelectionModel();
567 int i;
568
569 if (group != null)
570 {
571 for (i = 0; i < group.length ; i++)
572 {
573 getInside((Container)popup.getComponent(i));
574 }
575 }
576 }
577
578 /**
579 * This method will get all the components inside the JRootPane.
580 * (Precondition: pane != null)
581 * @param pane its the JRootPane we want to get the information from.
582 */
583 public void getRootPaneInfo (JRootPane pane)
584 {
585 Component[] group;
586 group = pane.getComponents();
587 int i;
588
589 if (group != null)
590 {
591 for (i = 0; i < group.length ; i++)
592 {
593
594 getInside((Container)pane.getComponent(i));
595 }
596 }
597 }
598
599 /**
600 * This method will get all the components inside the JLayeredPane.
601 * (Precondition: pane != null)
602 * @param pane its the JLayeredPane we want to get the information from.
603 */
604 public void getLayeredPaneInfo (JLayeredPane pane)
605 {
606 Component[] group;
607 group = pane.getComponents();
608 int i;
609
610 if (group != null)
611 {
612 for (i = 0; i < group.length ; i++)
613 {
614 getInside((Container)pane.getComponent(i));
615 }
616 }
617 }
618
619 /**
620 * This is a dummy method to get BasicInternalFrameTitlePane.
621 */
622 public void getInternalFrameTitleInfo (BasicInternalFrameTitlePane pane)
623 {
624 }
625
626 /**
627 * This method will add special column model and list selection
628 * listener to JTableHeader.
629 * (Precondition: header != null)
630 * @param header its the JTableHeader we want to get the information from.
631 */
632 public void getTableHeaderInfo (JTableHeader header)
633 {
634 TableColumnModel tcm;
635 tcm = header.getColumnModel();
636 ListSelectionModel lm;
637 lm = tcm.getSelectionModel();
638
639 if (tcm != null)
640 {
641 if (hash.containsKey(tcm) == false)
642 hash.put(tcm,header);
643 tcm.removeColumnModelListener(m);
644 tcm.addColumnModelListener(m);
645 }
646
647 if (lm != null)
648 {
649 if (hash.containsKey(lm) == false)
650 hash.put(lm,header);
651 lm.removeListSelectionListener(m);
652 lm.addListSelectionListener(m);
653 }
654 }
655
656 /**
657 * This method will get all components inside the JToolBar.
658 * (Precondition: tool != null)
659 * @param tool its the JToolBar we want to get the information from.
660 */
661 public void getToolBarInfo (JToolBar tool)
662 {
663 Component[] group;
664 group = tool.getComponents();
665 int i;
666
667 if (group != null)
668 {
669 for (i = 0; i < group.length ; i++)
670 {
671 getInside((Container)tool.getComponent(i));
672 }
673 }
674 }
675
676 /**
677 * This method will get all the components inside the JToolTip.
678 * (Precondition: tip != null)
679 * @param tip its the JToolTip we want to get the information from.
680 */
681 public void getToolTipInfo (JToolTip tip)
682 {
683 Component group;
684 group = tip.getComponent();
685 int i;
686
687 if (group != null)
688 {
689 getInside((Container) group);
690 }
691 }
692
693 /**
694 * This is the dummy method to get JSeparator.
695 */
696 public void getSeparatorInfo (JSeparator sept)
697 {
698 }
699
700 /**
701 * This method will get all the components inside the JDesktopPane.
702 * (Precondition: pane != null)
703 * @param pane its the JDesktopPane we want to get the information from.
704 */
705 public void getDesktopPaneInfo (JDesktopPane pane)
706 {
707 JInternalFrame[] group;
708 group = pane.getAllFrames();
709
710 if (group != null)
711 {
712 int i;
713
714 for ( i = 0 ; i < group.length ; i++ )
715 {
716 getInside((Container) group[i]);
717 }
718 }
719 }
720
721 /**
722 * This is a dummy method to catch null components.
723 */
724 public void getNullInfo ()
725 {
726 }
727
728 /**
729 * This method will add a special listener to a container and components inside it.
730 * This method is the gateway to all other methods in this class.
731 * @param comp its the Container we want to get the information from.
732 */
733 public void getInside(Container comp)
734 {
735 if (comp == null)
736 {
737 getNullInfo();
738 return;
739 }
740 else if (comp instanceof JApplet)
741 {
742 getAppletInfo ((JApplet) comp);
743 return;
744 }
745 else if (comp instanceof JSeparator)
746 {
747 getSeparatorInfo ((JSeparator) comp);
748 return;
749 }
750 else if (comp instanceof JWindow)
751 {
752 getWindowInfo((JWindow) comp);
753 return;
754 }
755 else if (comp instanceof JDialog)
756 {
757 getDialogInfo((JDialog) comp);
758 return;
759 }
760 else if (comp instanceof JComboBox)
761 {
762 getComboBoxInfo((JComboBox) comp);
763 return;
764 }
765 else if (comp instanceof JLabel)
766 {
767 getLabelInfo((JLabel) comp);
768 return;
769 }
770 else if (comp instanceof JTextComponent)
771 {
772 getTextAreaInfo((JTextComponent) comp);
773 return;
774 }
775 else if (comp instanceof JFrame)
776 {
777 getFrameInfo((JFrame) comp);
778 return;
779 }
780 else if (comp instanceof JPanel)
781 {
782 getPanelInfo((JPanel) comp);
783 return;
784 }
785 else if (comp instanceof JScrollPane)
786 {
787 getScrollInfo((JScrollPane) comp);
788 return;
789 }
790 else if (comp instanceof JScrollBar)
791 {
792 getScrollBarInfo ((JScrollBar) comp);
793 return;
794 }
795 else if (comp instanceof JViewport)
796 {
797 getViewPortInfo((JViewport) comp);
798 return;
799 }
800 else if (comp instanceof JTabbedPane)
801 {
802 getTabbedPaneInfo((JTabbedPane) comp);
803 return;
804 }
805 else if (comp instanceof Box)
806 {
807 getBoxInfo((Box) comp);
808 return;
809 }
810 else if (comp instanceof JToggleButton)
811 {
812 getToggleButtonInfo((JToggleButton) comp);
813 return;
814 }
815 else if (comp instanceof JSplitPane)
816 {
817 getSplitPaneInfo ((JSplitPane) comp);
818 return;
819 }
820 else if (comp instanceof JList)
821 {
822 getListInfo ((JList) comp);
823 return;
824 }
825 else if (comp instanceof JTree)
826 {
827 getTreeInfo ((JTree) comp);
828 return;
829 }
830 else if (comp instanceof JTable)
831 {
832 getTableInfo ((JTable) comp);
833 return;
834 }
835 else if (comp instanceof JSlider)
836 {
837 getSliderInfo ((JSlider) comp);
838 return;
839 }
840 else if (comp instanceof JSpinner)
841 {
842 getSpinnerInfo ((JSpinner) comp);
843 return;
844 }
845 else if (comp instanceof JProgressBar)
846 {
847 getProgressBarInfo ((JProgressBar) comp);
848 return;
849 }
850 else if (comp instanceof JButton)
851 {
852 getButtonInfo ((JButton) comp);
853 return;
854 }
855 else if (comp instanceof JMenu)
856 {
857 getMenuInfo ((JMenu) comp);
858 return;
859 }
860 else if (comp instanceof JMenuBar)
861 {
862 getMenuBarInfo ((JMenuBar) comp);
863 return;
864 }
865 else if (comp instanceof JMenuItem)
866 {
867 getMenuItemInfo ((JMenuItem) comp);
868 return;
869 }
870 else if (comp instanceof JOptionPane)
871 {
872 getOptionPaneInfo ((JOptionPane) comp);
873 return;
874 }
875 else if (comp instanceof BasicInternalFrameTitlePane)
876 {
877 getInternalFrameTitleInfo ((BasicInternalFrameTitlePane) comp);
878 return;
879 }
880 else if (comp instanceof JColorChooser)
881 {
882 getColorInfo ((JColorChooser) comp);
883 return;
884 }
885 else if (comp instanceof JFileChooser)
886 {
887 getFileChooserInfo ((JFileChooser) comp);
888 return;
889 }
890 else if (comp instanceof JDesktopPane)
891 {
892 getDesktopPaneInfo ((JDesktopPane) comp);
893 return;
894 }
895 else if (comp instanceof JInternalFrame)
896 {
897 getInternalFrameInfo ((JInternalFrame) comp);
898 return;
899 }
900 else if (comp instanceof JLayeredPane)
901 {
902 getLayeredPaneInfo ((JLayeredPane) comp);
903 return;
904 }
905 else if (comp instanceof JPopupMenu)
906 {
907 getPopUpMenuInfo ((JPopupMenu) comp);
908 return;
909 }
910 else if (comp instanceof JRootPane)
911 {
912 getRootPaneInfo ((JRootPane) comp);
913 return;
914 }
915 else if (comp instanceof JTableHeader)
916 {
917 getTableHeaderInfo ((JTableHeader) comp);
918 return;
919 }
920 else if (comp instanceof JToolBar)
921 {
922 getToolBarInfo ((JToolBar) comp);
923 return;
924 }
925 else if (comp instanceof JToolTip)
926 {
927 getToolTipInfo ((JToolTip) comp);
928 return;
929 }
930 else
931 {
932 getCompInfo (comp);
933 return;
934 }
935 }
936}
937
938
939
940
941
942
943
Note: See TracBrowser for help on using the repository browser.