Merge branch 'JAL-3878_ws-overhaul-3' into with_ws_overhaul-3
[jalview.git] / src / jalview / gui / AnnotationColumnChooser.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21
22 package jalview.gui;
23
24 import jalview.datamodel.AlignmentAnnotation;
25 import jalview.datamodel.HiddenColumns;
26 import jalview.io.cache.JvCacheableInputBox;
27 import jalview.schemes.AnnotationColourGradient;
28 import jalview.util.MessageManager;
29 import jalview.util.Platform;
30 import jalview.viewmodel.annotationfilter.AnnotationFilterParameter;
31
32 import java.awt.BorderLayout;
33 import java.awt.CardLayout;
34 import java.awt.Color;
35 import java.awt.Dimension;
36 import java.awt.event.ActionEvent;
37 import java.awt.event.ActionListener;
38 import java.awt.event.FocusAdapter;
39 import java.awt.event.FocusEvent;
40 import java.awt.event.ItemEvent;
41 import java.awt.event.ItemListener;
42 import java.awt.event.KeyEvent;
43
44 import javax.swing.ButtonGroup;
45 import javax.swing.JCheckBox;
46 import javax.swing.JComboBox;
47 import javax.swing.JInternalFrame;
48 import javax.swing.JLayeredPane;
49 import javax.swing.JPanel;
50 import javax.swing.JRadioButton;
51 import javax.swing.border.TitledBorder;
52
53 import net.miginfocom.swing.MigLayout;
54
55 @SuppressWarnings("serial")
56 public class AnnotationColumnChooser extends AnnotationRowFilter
57         implements ItemListener
58 {
59   private JPanel switchableViewsPanel = new JPanel(new CardLayout());
60
61   private JPanel annotationComboBoxPanel = new JPanel();
62
63   private StructureFilterPanel gStructureFilterPanel;
64
65   private StructureFilterPanel ngStructureFilterPanel;
66
67   private StructureFilterPanel currentStructureFilterPanel;
68
69   private SearchPanel currentSearchPanel;
70
71   private SearchPanel gSearchPanel;
72
73   private SearchPanel ngSearchPanel;
74
75   private FurtherActionPanel currentFurtherActionPanel;
76
77   private FurtherActionPanel gFurtherActionPanel;
78
79   private FurtherActionPanel ngFurtherActionPanel;
80
81   public static final int ACTION_OPTION_SELECT = 1;
82
83   public static int ACTION_OPTION_HIDE = 2;
84
85   public static String NO_GRAPH_VIEW = "0";
86
87   public static String GRAPH_VIEW = "1";
88
89   private int actionOption = ACTION_OPTION_SELECT;
90
91   private HiddenColumns oldHiddenColumns;
92
93   protected static int MIN_WIDTH = (Platform.isJS() ? 370 : 420);
94
95   protected static int MIN_HEIGHT = (Platform.isJS() ? 370 : 430);
96
97   public AnnotationColumnChooser(AlignViewport av, final AlignmentPanel ap)
98   {
99     super(av, ap);
100     frame = new JInternalFrame();
101     frame.setContentPane(this);
102     frame.setLayer(JLayeredPane.PALETTE_LAYER);
103     Desktop.addInternalFrame(frame,
104             MessageManager.getString("label.select_by_annotation"), 0, 0);
105     // BH note: MIGLayout ignores this completely,
106     // possibly creating a frame smaller than specified:
107     frame.setMinimumSize(new Dimension(MIN_WIDTH, MIN_HEIGHT));
108
109     addSliderChangeListener();
110     addSliderMouseListeners();
111
112     if (av.getAlignment().getAlignmentAnnotation() == null)
113     {
114       return;
115     }
116     setOldHiddenColumns(av.getAlignment().getHiddenColumns());
117     adjusting = true;
118
119     setAnnotations(new JComboBox<>(getAnnotationItems(false)));
120     populateThresholdComboBox(threshold);
121     AnnotationColumnChooser lastChooser = av
122             .getAnnotationColumnSelectionState();
123     // restore Object state from the previous session if one exists
124     if (lastChooser != null)
125     {
126       currentSearchPanel = lastChooser.getCurrentSearchPanel();
127       currentStructureFilterPanel = lastChooser
128               .getCurrentStructureFilterPanel();
129       annotations.setSelectedIndex(
130               lastChooser.getAnnotations().getSelectedIndex());
131       threshold.setSelectedIndex(
132               lastChooser.getThreshold().getSelectedIndex());
133       actionOption = lastChooser.getActionOption();
134       percentThreshold
135               .setSelected(lastChooser.percentThreshold.isSelected());
136     }
137
138     try
139     {
140       jbInit();
141     } catch (Exception ex)
142     {
143     }
144     adjusting = false;
145
146     updateView();
147     frame.invalidate();
148     frame.pack();
149   }
150
151   @Override
152   protected void jbInit()
153   {
154     super.jbInit();
155
156     JPanel thresholdPanel = new JPanel();
157     thresholdPanel.setBorder(new TitledBorder(
158             MessageManager.getString("label.threshold_filter")));
159     thresholdPanel.setBackground(Color.white);
160     thresholdPanel.setFont(JvSwingUtils.getLabelFont());
161     thresholdPanel.setLayout(new MigLayout("", "[left][right]", "[][]"));
162
163     percentThreshold.setBackground(Color.white);
164     percentThreshold.setFont(JvSwingUtils.getLabelFont());
165
166     JPanel actionPanel = new JPanel();
167     actionPanel.setBackground(Color.white);
168     actionPanel.setFont(JvSwingUtils.getLabelFont());
169
170     JPanel graphFilterView = new JPanel();
171     graphFilterView.setLayout(new MigLayout("", "[left][right]", "[][]"));
172     graphFilterView.setBackground(Color.white);
173
174     JPanel noGraphFilterView = new JPanel();
175     noGraphFilterView.setLayout(new MigLayout("", "[left][right]", "[][]"));
176     noGraphFilterView.setBackground(Color.white);
177
178     annotationComboBoxPanel.setBackground(Color.white);
179     annotationComboBoxPanel.setFont(JvSwingUtils.getLabelFont());
180
181     gSearchPanel = new SearchPanel(this);
182     ngSearchPanel = new SearchPanel(this);
183     gFurtherActionPanel = new FurtherActionPanel(this);
184     ngFurtherActionPanel = new FurtherActionPanel(this);
185     gStructureFilterPanel = new StructureFilterPanel(this);
186     ngStructureFilterPanel = new StructureFilterPanel(this);
187
188     thresholdPanel.add(getThreshold());
189     thresholdPanel.add(percentThreshold, "wrap");
190     thresholdPanel.add(slider, "grow");
191     thresholdPanel.add(thresholdValue, "span, wrap");
192
193     actionPanel.add(ok);
194     actionPanel.add(cancel);
195
196     graphFilterView.add(gSearchPanel, "grow, span, wrap");
197     graphFilterView.add(gStructureFilterPanel, "grow, span, wrap");
198     graphFilterView.add(thresholdPanel, "grow, span, wrap");
199     graphFilterView.add(gFurtherActionPanel);
200
201     noGraphFilterView.add(ngSearchPanel, "grow, span, wrap");
202     noGraphFilterView.add(ngStructureFilterPanel, "grow, span, wrap");
203     noGraphFilterView.add(ngFurtherActionPanel);
204
205     annotationComboBoxPanel.add(getAnnotations());
206     switchableViewsPanel.add(noGraphFilterView,
207             AnnotationColumnChooser.NO_GRAPH_VIEW);
208     switchableViewsPanel.add(graphFilterView,
209             AnnotationColumnChooser.GRAPH_VIEW);
210     this.setLayout(new BorderLayout());
211     this.add(annotationComboBoxPanel, java.awt.BorderLayout.PAGE_START);
212     this.add(switchableViewsPanel, java.awt.BorderLayout.CENTER);
213     this.add(actionPanel, java.awt.BorderLayout.SOUTH);
214
215     selectedAnnotationChanged();
216     updateThresholdPanelToolTip();
217     this.validate();
218   }
219
220   protected void updateThresholdPanelToolTip()
221   {
222     thresholdValue.setToolTipText("");
223     slider.setToolTipText("");
224
225     String defaultTtip = MessageManager
226             .getString("info.change_threshold_mode_to_enable");
227
228     String thresh = getThreshold().getSelectedItem().toString();
229     if (thresh.equalsIgnoreCase("No Threshold"))
230     {
231       thresholdValue.setToolTipText(defaultTtip);
232       slider.setToolTipText(defaultTtip);
233     }
234   }
235
236   @Override
237   protected void reset()
238   {
239     if (this.getOldHiddenColumns() != null)
240     {
241       av.getColumnSelection().clear();
242
243       if (av.getAnnotationColumnSelectionState() != null)
244       {
245         HiddenColumns oldHidden = av.getAnnotationColumnSelectionState()
246                 .getOldHiddenColumns();
247         av.getAlignment().setHiddenColumns(oldHidden);
248       }
249       av.sendSelection();
250       ap.paintAlignment(true, true);
251     }
252   }
253
254   @Override
255   public void valueChanged(boolean updateAllAnnotation)
256   {
257     if (slider.isEnabled())
258     {
259       getCurrentAnnotation().threshold.value = getSliderValue();
260       updateView();
261       propagateSeqAssociatedThreshold(updateAllAnnotation,
262               getCurrentAnnotation());
263       ap.paintAlignment(false, false);
264     }
265   }
266
267   @Override
268   public void updateView()
269   {
270     // Check if combobox is still adjusting
271     if (adjusting)
272     {
273       return;
274     }
275
276     AnnotationFilterParameter filterParams = new AnnotationFilterParameter();
277
278     setCurrentAnnotation(av.getAlignment()
279             .getAlignmentAnnotation()[annmap[getAnnotations()
280                     .getSelectedIndex()]]);
281
282     int selectedThresholdItem = getSelectedThresholdItem(
283             getThreshold().getSelectedIndex());
284
285     slider.setEnabled(true);
286     thresholdValue.setEnabled(true);
287     percentThreshold.setEnabled(true);
288
289     final AlignmentAnnotation currentAnnotation = getCurrentAnnotation();
290     if (selectedThresholdItem == AnnotationColourGradient.NO_THRESHOLD)
291     {
292       slider.setEnabled(false);
293       thresholdValue.setEnabled(false);
294       thresholdValue.setText("");
295       percentThreshold.setEnabled(false);
296       // build filter params
297     }
298     else if (selectedThresholdItem != AnnotationColourGradient.NO_THRESHOLD)
299     {
300       if (currentAnnotation.threshold == null)
301       {
302         currentAnnotation.setThreshold(new jalview.datamodel.GraphLine(
303                 (currentAnnotation.graphMax - currentAnnotation.graphMin)
304                         / 2f,
305                 "Threshold", Color.black));
306       }
307
308       adjusting = true;
309
310       setSliderModel(currentAnnotation.graphMin, currentAnnotation.graphMax,
311               currentAnnotation.threshold.value);
312
313       setThresholdValueText();
314
315       slider.setEnabled(true);
316       thresholdValue.setEnabled(true);
317       adjusting = false;
318
319       // build filter params
320       filterParams.setThresholdType(
321               AnnotationFilterParameter.ThresholdType.NO_THRESHOLD);
322       if (currentAnnotation.isQuantitative())
323       {
324         filterParams.setThresholdValue(currentAnnotation.threshold.value);
325
326         if (selectedThresholdItem == AnnotationColourGradient.ABOVE_THRESHOLD)
327         {
328           filterParams.setThresholdType(
329                   AnnotationFilterParameter.ThresholdType.ABOVE_THRESHOLD);
330         }
331         else if (selectedThresholdItem == AnnotationColourGradient.BELOW_THRESHOLD)
332         {
333           filterParams.setThresholdType(
334                   AnnotationFilterParameter.ThresholdType.BELOW_THRESHOLD);
335         }
336       }
337     }
338
339     updateThresholdPanelToolTip();
340     if (currentStructureFilterPanel != null)
341     {
342       if (currentStructureFilterPanel.alphaHelix.isSelected())
343       {
344         filterParams.setFilterAlphaHelix(true);
345       }
346       if (currentStructureFilterPanel.betaStrand.isSelected())
347       {
348         filterParams.setFilterBetaSheet(true);
349       }
350       if (currentStructureFilterPanel.turn.isSelected())
351       {
352         filterParams.setFilterTurn(true);
353       }
354     }
355
356     if (currentSearchPanel != null)
357     {
358       if (!currentSearchPanel.searchBox.getUserInput().isEmpty())
359       {
360         filterParams.setRegexString(
361                 currentSearchPanel.searchBox.getUserInput());
362         if (currentSearchPanel.displayName.isSelected())
363         {
364           filterParams.addRegexSearchField(
365                   AnnotationFilterParameter.SearchableAnnotationField.DISPLAY_STRING);
366         }
367         if (currentSearchPanel.description.isSelected())
368         {
369           filterParams.addRegexSearchField(
370                   AnnotationFilterParameter.SearchableAnnotationField.DESCRIPTION);
371         }
372       }
373     }
374
375     // show hidden columns here, before changing the column selection in
376     // filterAnnotations, because showing hidden columns has the side effect of
377     // adding them to the selection
378     av.showAllHiddenColumns();
379     av.getColumnSelection().filterAnnotations(currentAnnotation.annotations,
380             filterParams);
381
382     boolean hideCols = getActionOption() == ACTION_OPTION_HIDE;
383     if (hideCols)
384     {
385       av.hideSelectedColumns();
386     }
387     av.sendSelection();
388
389     filterParams = null;
390     av.setAnnotationColumnSelectionState(this);
391     // only update overview and structures if columns were hidden
392     ap.paintAlignment(hideCols, hideCols);
393   }
394
395   public HiddenColumns getOldHiddenColumns()
396   {
397     return oldHiddenColumns;
398   }
399
400   public void setOldHiddenColumns(HiddenColumns currentHiddenColumns)
401   {
402     if (currentHiddenColumns != null)
403     {
404       this.oldHiddenColumns = new HiddenColumns(currentHiddenColumns);
405     }
406   }
407
408   public FurtherActionPanel getCurrentFutherActionPanel()
409   {
410     return currentFurtherActionPanel;
411   }
412
413   public void setCurrentFutherActionPanel(
414           FurtherActionPanel currentFutherActionPanel)
415   {
416     this.currentFurtherActionPanel = currentFutherActionPanel;
417   }
418
419   public SearchPanel getCurrentSearchPanel()
420   {
421     return currentSearchPanel;
422   }
423
424   public void setCurrentSearchPanel(SearchPanel currentSearchPanel)
425   {
426     this.currentSearchPanel = currentSearchPanel;
427   }
428
429   public int getActionOption()
430   {
431     return actionOption;
432   }
433
434   public void setActionOption(int actionOption)
435   {
436     this.actionOption = actionOption;
437   }
438
439   public StructureFilterPanel getCurrentStructureFilterPanel()
440   {
441     return currentStructureFilterPanel;
442   }
443
444   public void setCurrentStructureFilterPanel(
445           StructureFilterPanel currentStructureFilterPanel)
446   {
447     this.currentStructureFilterPanel = currentStructureFilterPanel;
448   }
449
450   public void select_action(ActionEvent actionEvent)
451   {
452     JRadioButton radioButton = (JRadioButton) actionEvent.getSource();
453     if (radioButton.isSelected())
454     {
455       setActionOption(ACTION_OPTION_SELECT);
456       updateView();
457     }
458   }
459
460   public void hide_action(ActionEvent actionEvent)
461   {
462     JRadioButton radioButton = (JRadioButton) actionEvent.getSource();
463     if (radioButton.isSelected())
464     {
465       setActionOption(ACTION_OPTION_HIDE);
466       updateView();
467     }
468   }
469
470   @Override
471   public void itemStateChanged(ItemEvent e)
472   {
473     selectedAnnotationChanged();
474   }
475
476   @Override
477   public void selectedAnnotationChanged()
478   {
479     String currentView = AnnotationColumnChooser.NO_GRAPH_VIEW;
480     if (av.getAlignment().getAlignmentAnnotation()[annmap[getAnnotations()
481             .getSelectedIndex()]].isQuantitative())
482     {
483       currentView = AnnotationColumnChooser.GRAPH_VIEW;
484     }
485     saveCache();
486     gSearchPanel.syncState();
487     gFurtherActionPanel.syncState();
488     gStructureFilterPanel.syncState();
489
490     ngSearchPanel.syncState();
491     ngFurtherActionPanel.syncState();
492     ngStructureFilterPanel.syncState();
493
494     CardLayout switchableViewsLayout = (CardLayout) switchableViewsPanel
495             .getLayout();
496     switchableViewsLayout.show(switchableViewsPanel, currentView);
497     updateView();
498   }
499
500   public class FurtherActionPanel extends JPanel
501   {
502     private AnnotationColumnChooser aColChooser;
503
504     private JRadioButton hideOption = new JRadioButton();
505
506     private JRadioButton selectOption = new JRadioButton();
507
508     private ButtonGroup optionsGroup = new ButtonGroup();
509
510     public FurtherActionPanel(AnnotationColumnChooser aColChooser)
511     {
512       this.aColChooser = aColChooser;
513       JvSwingUtils.jvInitComponent(selectOption, "action.select");
514       selectOption.addActionListener(new ActionListener()
515       {
516         @Override
517         public void actionPerformed(ActionEvent actionEvent)
518         {
519           selectRadioAction(actionEvent);
520         }
521       });
522
523       JvSwingUtils.jvInitComponent(hideOption, "action.hide");
524       hideOption.addActionListener(new ActionListener()
525       {
526         @Override
527         public void actionPerformed(ActionEvent actionEvent)
528         {
529           hideRadioAction(actionEvent);
530         }
531       });
532
533       optionsGroup.add(selectOption);
534       optionsGroup.add(hideOption);
535       optionsGroup.setSelected(selectOption.getModel(), true);
536
537       JvSwingUtils.jvInitComponent(this);
538       syncState();
539
540       this.add(selectOption);
541       this.add(hideOption);
542     }
543
544     public void selectRadioAction(ActionEvent actionEvent)
545     {
546       aColChooser.setCurrentFutherActionPanel(this);
547       aColChooser.select_action(actionEvent);
548     }
549
550     public void hideRadioAction(ActionEvent actionEvent)
551     {
552       aColChooser.setCurrentFutherActionPanel(this);
553       aColChooser.hide_action(actionEvent);
554     }
555
556     public void syncState()
557     {
558       if (aColChooser
559               .getActionOption() == AnnotationColumnChooser.ACTION_OPTION_HIDE)
560       {
561         this.optionsGroup.setSelected(this.hideOption.getModel(), true);
562       }
563       else
564       {
565         this.optionsGroup.setSelected(this.selectOption.getModel(), true);
566       }
567     }
568   }
569
570   public class StructureFilterPanel extends JPanel
571   {
572     private AnnotationColumnChooser aColChooser;
573
574     private JCheckBox alphaHelix = new JCheckBox();
575
576     private JCheckBox betaStrand = new JCheckBox();
577
578     private JCheckBox turn = new JCheckBox();
579
580     private JCheckBox all = new JCheckBox();
581
582     public StructureFilterPanel(AnnotationColumnChooser aColChooser)
583     {
584       this.aColChooser = aColChooser;
585
586       JvSwingUtils.jvInitComponent(alphaHelix, "label.alpha_helix");
587       alphaHelix.addActionListener(new ActionListener()
588       {
589         @Override
590         public void actionPerformed(ActionEvent actionEvent)
591         {
592           alphaHelix_actionPerformed();
593         }
594       });
595
596       JvSwingUtils.jvInitComponent(betaStrand, "label.beta_strand");
597       betaStrand.addActionListener(new ActionListener()
598       {
599         @Override
600         public void actionPerformed(ActionEvent actionEvent)
601         {
602           betaStrand_actionPerformed();
603         }
604       });
605
606       JvSwingUtils.jvInitComponent(turn, "label.turn");
607       turn.addActionListener(new ActionListener()
608       {
609         @Override
610         public void actionPerformed(ActionEvent actionEvent)
611         {
612           turn_actionPerformed();
613         }
614       });
615
616       JvSwingUtils.jvInitComponent(all, "label.select_all");
617       all.addActionListener(new ActionListener()
618       {
619         @Override
620         public void actionPerformed(ActionEvent actionEvent)
621         {
622           all_actionPerformed();
623         }
624       });
625
626       this.setBorder(new TitledBorder(
627               MessageManager.getString("label.structures_filter")));
628       JvSwingUtils.jvInitComponent(this);
629
630       this.add(all);
631       this.add(alphaHelix);
632       this.add(betaStrand);
633       this.add(turn);
634     }
635
636     public void alphaHelix_actionPerformed()
637     {
638       updateSelectAllState();
639       aColChooser.setCurrentStructureFilterPanel(this);
640       aColChooser.updateView();
641     }
642
643     public void betaStrand_actionPerformed()
644     {
645       updateSelectAllState();
646       aColChooser.setCurrentStructureFilterPanel(this);
647       aColChooser.updateView();
648     }
649
650     public void turn_actionPerformed()
651     {
652       updateSelectAllState();
653       aColChooser.setCurrentStructureFilterPanel(this);
654       aColChooser.updateView();
655     }
656
657     public void all_actionPerformed()
658     {
659       if (all.isSelected())
660       {
661         alphaHelix.setSelected(true);
662         betaStrand.setSelected(true);
663         turn.setSelected(true);
664       }
665       else
666       {
667         alphaHelix.setSelected(false);
668         betaStrand.setSelected(false);
669         turn.setSelected(false);
670       }
671       aColChooser.setCurrentStructureFilterPanel(this);
672       aColChooser.updateView();
673     }
674
675     public void updateSelectAllState()
676     {
677       if (alphaHelix.isSelected() && betaStrand.isSelected()
678               && turn.isSelected())
679       {
680         all.setSelected(true);
681       }
682       else
683       {
684         all.setSelected(false);
685       }
686     }
687
688     public void syncState()
689     {
690       StructureFilterPanel sfp = aColChooser
691               .getCurrentStructureFilterPanel();
692       if (sfp != null)
693       {
694         alphaHelix.setSelected(sfp.alphaHelix.isSelected());
695         betaStrand.setSelected(sfp.betaStrand.isSelected());
696         turn.setSelected(sfp.turn.isSelected());
697         if (sfp.all.isSelected())
698         {
699           all.setSelected(true);
700           alphaHelix.setSelected(true);
701           betaStrand.setSelected(true);
702           turn.setSelected(true);
703         }
704       }
705
706     }
707   }
708
709   public class SearchPanel extends JPanel
710   {
711     private AnnotationColumnChooser aColChooser;
712
713     private JCheckBox displayName = new JCheckBox();
714
715     private JCheckBox description = new JCheckBox();
716
717     private static final String FILTER_BY_ANN_CACHE_KEY = "CACHE.SELECT_FILTER_BY_ANNOT";
718
719     public JvCacheableInputBox<String> searchBox = new JvCacheableInputBox<>(
720             FILTER_BY_ANN_CACHE_KEY, 23);
721
722     public SearchPanel(AnnotationColumnChooser aColChooser)
723     {
724
725       this.aColChooser = aColChooser;
726       JvSwingUtils.jvInitComponent(this);
727       this.setBorder(new TitledBorder(
728               MessageManager.getString("label.search_filter")));
729
730       searchBox.getComponent().setToolTipText(
731               MessageManager.getString("info.enter_search_text_here"));
732       searchBox.addKeyListener(new java.awt.event.KeyAdapter()
733       {
734         @Override
735         public void keyPressed(KeyEvent e)
736         {
737           if (e.getKeyCode() == KeyEvent.VK_ENTER)
738           {
739             e.consume();
740             searchStringAction();
741           }
742         }
743       });
744       searchBox.addFocusListener(new FocusAdapter()
745       {
746         @Override
747         public void focusLost(FocusEvent e)
748         {
749           searchStringAction();
750         }
751       });
752
753       JvSwingUtils.jvInitComponent(displayName, "label.label");
754       displayName.addActionListener(new ActionListener()
755       {
756         @Override
757         public void actionPerformed(ActionEvent actionEvent)
758         {
759           displayNameCheckboxAction();
760         }
761       });
762
763       JvSwingUtils.jvInitComponent(description, "label.description");
764       description.addActionListener(new ActionListener()
765       {
766         @Override
767         public void actionPerformed(ActionEvent actionEvent)
768         {
769           descriptionCheckboxAction();
770         }
771       });
772
773       syncState();
774       this.add(searchBox.getComponent());
775       this.add(displayName);
776       this.add(description);
777     }
778
779     public void displayNameCheckboxAction()
780     {
781       aColChooser.setCurrentSearchPanel(this);
782       aColChooser.updateView();
783     }
784
785     public void descriptionCheckboxAction()
786     {
787       aColChooser.setCurrentSearchPanel(this);
788       aColChooser.updateView();
789     }
790
791     public void searchStringAction()
792     {
793       aColChooser.setCurrentSearchPanel(this);
794       aColChooser.updateView();
795       updateSearchPanelToolTips();
796       searchBox.updateCache();
797     }
798
799     public void syncState()
800     {
801       SearchPanel sp = aColChooser.getCurrentSearchPanel();
802       if (sp != null)
803       {
804         description.setEnabled(sp.description.isEnabled());
805         description.setSelected(sp.description.isSelected());
806
807         displayName.setEnabled(sp.displayName.isEnabled());
808         displayName.setSelected(sp.displayName.isSelected());
809
810         searchBox.setSelectedItem(sp.searchBox.getUserInput());
811       }
812       updateSearchPanelToolTips();
813     }
814
815     public void updateSearchPanelToolTips()
816     {
817       String defaultTtip = MessageManager
818               .getString("info.enter_search_text_to_enable");
819       String labelTtip = MessageManager.formatMessage(
820               "info.search_in_annotation_label",
821               annotations.getSelectedItem().toString());
822       String descTtip = MessageManager.formatMessage(
823               "info.search_in_annotation_description",
824               annotations.getSelectedItem().toString());
825       displayName.setToolTipText(
826               displayName.isEnabled() ? labelTtip : defaultTtip);
827       description.setToolTipText(
828               description.isEnabled() ? descTtip : defaultTtip);
829     }
830   }
831
832   @Override
833   public void ok_actionPerformed()
834   {
835     saveCache();
836     super.ok_actionPerformed();
837   }
838
839   @Override
840   public void cancel_actionPerformed()
841   {
842     saveCache();
843     super.cancel_actionPerformed();
844   }
845
846   private void saveCache()
847   {
848     gSearchPanel.searchBox.persistCache();
849     ngSearchPanel.searchBox.persistCache();
850     gSearchPanel.searchBox.updateCache();
851     ngSearchPanel.searchBox.updateCache();
852   }
853 }