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