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