8b66b8e540f48cffad5d6a72c02e756bfb37c1c9
[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   protected static int MIN_HEIGHT = (Platform.isJS() ? 370 : 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"), 0,
104             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
304                         - currentAnnotation.graphMin) / 2f,
305                 "Threshold", Color.black));
306       }
307
308       adjusting = true;
309
310       setSliderModel(currentAnnotation.graphMin,
311               currentAnnotation.graphMax,
312               currentAnnotation.threshold.value);
313
314       setThresholdValueText();
315
316       slider.setEnabled(true);
317       thresholdValue.setEnabled(true);
318       adjusting = false;
319
320       // build filter params
321       filterParams.setThresholdType(
322               AnnotationFilterParameter.ThresholdType.NO_THRESHOLD);
323       if (currentAnnotation.isQuantitative())
324       {
325         filterParams
326                 .setThresholdValue(currentAnnotation.threshold.value);
327
328         if (selectedThresholdItem == AnnotationColourGradient.ABOVE_THRESHOLD)
329         {
330           filterParams.setThresholdType(
331                   AnnotationFilterParameter.ThresholdType.ABOVE_THRESHOLD);
332         }
333         else if (selectedThresholdItem == AnnotationColourGradient.BELOW_THRESHOLD)
334         {
335           filterParams.setThresholdType(
336                   AnnotationFilterParameter.ThresholdType.BELOW_THRESHOLD);
337         }
338       }
339     }
340
341     updateThresholdPanelToolTip();
342     if (currentStructureFilterPanel != null)
343     {
344       if (currentStructureFilterPanel.alphaHelix.isSelected())
345       {
346         filterParams.setFilterAlphaHelix(true);
347       }
348       if (currentStructureFilterPanel.betaStrand.isSelected())
349       {
350         filterParams.setFilterBetaSheet(true);
351       }
352       if (currentStructureFilterPanel.turn.isSelected())
353       {
354         filterParams.setFilterTurn(true);
355       }
356     }
357
358     if (currentSearchPanel != null)
359     {
360       if (!currentSearchPanel.searchBox.getUserInput().isEmpty())
361       {
362         filterParams.setRegexString(
363                 currentSearchPanel.searchBox.getUserInput());
364         if (currentSearchPanel.displayName.isSelected())
365         {
366           filterParams.addRegexSearchField(
367                   AnnotationFilterParameter.SearchableAnnotationField.DISPLAY_STRING);
368         }
369         if (currentSearchPanel.description.isSelected())
370         {
371           filterParams.addRegexSearchField(
372                   AnnotationFilterParameter.SearchableAnnotationField.DESCRIPTION);
373         }
374       }
375     }
376
377     // show hidden columns here, before changing the column selection in
378     // filterAnnotations, because showing hidden columns has the side effect of
379     // adding them to the selection
380     av.showAllHiddenColumns();
381     av.getColumnSelection().filterAnnotations(
382             currentAnnotation.annotations, filterParams);
383
384     boolean hideCols = getActionOption() == ACTION_OPTION_HIDE;
385     if (hideCols)
386     {
387       av.hideSelectedColumns();
388     }
389     av.sendSelection();
390
391     filterParams = null;
392     av.setAnnotationColumnSelectionState(this);
393     // only update overview and structures if columns were hidden
394     ap.paintAlignment(hideCols, hideCols);
395   }
396
397   public HiddenColumns getOldHiddenColumns()
398   {
399     return oldHiddenColumns;
400   }
401
402   public void setOldHiddenColumns(HiddenColumns currentHiddenColumns)
403   {
404     if (currentHiddenColumns != null)
405     {
406       this.oldHiddenColumns = new HiddenColumns(currentHiddenColumns);
407     }
408   }
409
410   public FurtherActionPanel getCurrentFutherActionPanel()
411   {
412     return currentFurtherActionPanel;
413   }
414
415   public void setCurrentFutherActionPanel(
416           FurtherActionPanel currentFutherActionPanel)
417   {
418     this.currentFurtherActionPanel = currentFutherActionPanel;
419   }
420
421   public SearchPanel getCurrentSearchPanel()
422   {
423     return currentSearchPanel;
424   }
425
426   public void setCurrentSearchPanel(SearchPanel currentSearchPanel)
427   {
428     this.currentSearchPanel = currentSearchPanel;
429   }
430
431   public int getActionOption()
432   {
433     return actionOption;
434   }
435
436   public void setActionOption(int actionOption)
437   {
438     this.actionOption = actionOption;
439   }
440
441   public StructureFilterPanel getCurrentStructureFilterPanel()
442   {
443     return currentStructureFilterPanel;
444   }
445
446   public void setCurrentStructureFilterPanel(
447           StructureFilterPanel currentStructureFilterPanel)
448   {
449     this.currentStructureFilterPanel = currentStructureFilterPanel;
450   }
451
452   public void select_action(ActionEvent actionEvent)
453   {
454     JRadioButton radioButton = (JRadioButton) actionEvent.getSource();
455     if (radioButton.isSelected())
456     {
457       setActionOption(ACTION_OPTION_SELECT);
458       updateView();
459     }
460   }
461
462   public void hide_action(ActionEvent actionEvent)
463   {
464     JRadioButton radioButton = (JRadioButton) actionEvent.getSource();
465     if (radioButton.isSelected())
466     {
467       setActionOption(ACTION_OPTION_HIDE);
468       updateView();
469     }
470   }
471
472   @Override
473   public void itemStateChanged(ItemEvent e)
474   {
475     selectedAnnotationChanged();
476   }
477
478   @Override
479   public void selectedAnnotationChanged()
480   {
481     String currentView = AnnotationColumnChooser.NO_GRAPH_VIEW;
482     if (av.getAlignment().getAlignmentAnnotation()[annmap[getAnnotations()
483             .getSelectedIndex()]].isQuantitative())
484     {
485       currentView = AnnotationColumnChooser.GRAPH_VIEW;
486     }
487     saveCache();
488     gSearchPanel.syncState();
489     gFurtherActionPanel.syncState();
490     gStructureFilterPanel.syncState();
491
492     ngSearchPanel.syncState();
493     ngFurtherActionPanel.syncState();
494     ngStructureFilterPanel.syncState();
495
496     CardLayout switchableViewsLayout = (CardLayout) switchableViewsPanel
497             .getLayout();
498         switchableViewsLayout.show(switchableViewsPanel, currentView);
499     updateView();
500   }
501
502   public class FurtherActionPanel extends JPanel
503   {
504     private AnnotationColumnChooser aColChooser;
505
506     private JRadioButton hideOption = new JRadioButton();
507
508     private JRadioButton selectOption = new JRadioButton();
509
510     private ButtonGroup optionsGroup = new ButtonGroup();
511
512     public FurtherActionPanel(AnnotationColumnChooser aColChooser)
513     {
514       this.aColChooser = aColChooser;
515       JvSwingUtils.jvInitComponent(selectOption, "action.select");
516       selectOption.addActionListener(new ActionListener()
517       {
518         @Override
519         public void actionPerformed(ActionEvent actionEvent)
520         {
521           selectRadioAction(actionEvent);
522         }
523       });
524
525       JvSwingUtils.jvInitComponent(hideOption, "action.hide");
526       hideOption.addActionListener(new ActionListener()
527       {
528         @Override
529         public void actionPerformed(ActionEvent actionEvent)
530         {
531           hideRadioAction(actionEvent);
532         }
533       });
534
535       optionsGroup.add(selectOption);
536       optionsGroup.add(hideOption);
537       optionsGroup.setSelected(selectOption.getModel(), true);
538
539       JvSwingUtils.jvInitComponent(this);
540       syncState();
541
542       this.add(selectOption);
543       this.add(hideOption);
544     }
545
546     public void selectRadioAction(ActionEvent actionEvent)
547     {
548       aColChooser.setCurrentFutherActionPanel(this);
549       aColChooser.select_action(actionEvent);
550     }
551
552     public void hideRadioAction(ActionEvent actionEvent)
553     {
554       aColChooser.setCurrentFutherActionPanel(this);
555       aColChooser.hide_action(actionEvent);
556     }
557
558     public void syncState()
559     {
560       if (aColChooser
561               .getActionOption() == AnnotationColumnChooser.ACTION_OPTION_HIDE)
562       {
563         this.optionsGroup.setSelected(this.hideOption.getModel(), true);
564       }
565       else
566       {
567         this.optionsGroup.setSelected(this.selectOption.getModel(), true);
568       }
569     }
570   }
571
572   public class StructureFilterPanel extends JPanel
573   {
574     private AnnotationColumnChooser aColChooser;
575
576     private JCheckBox alphaHelix = new JCheckBox();
577
578     private JCheckBox betaStrand = new JCheckBox();
579
580     private JCheckBox turn = new JCheckBox();
581
582     private JCheckBox all = new JCheckBox();
583
584     public StructureFilterPanel(AnnotationColumnChooser aColChooser)
585     {
586       this.aColChooser = aColChooser;
587
588       JvSwingUtils.jvInitComponent(alphaHelix, "label.alpha_helix");
589       alphaHelix.addActionListener(new ActionListener()
590       {
591         @Override
592         public void actionPerformed(ActionEvent actionEvent)
593         {
594           alphaHelix_actionPerformed();
595         }
596       });
597
598       JvSwingUtils.jvInitComponent(betaStrand, "label.beta_strand");
599       betaStrand.addActionListener(new ActionListener()
600       {
601         @Override
602         public void actionPerformed(ActionEvent actionEvent)
603         {
604           betaStrand_actionPerformed();
605         }
606       });
607
608       JvSwingUtils.jvInitComponent(turn, "label.turn");
609       turn.addActionListener(new ActionListener()
610       {
611         @Override
612         public void actionPerformed(ActionEvent actionEvent)
613         {
614           turn_actionPerformed();
615         }
616       });
617
618       JvSwingUtils.jvInitComponent(all, "label.select_all");
619       all.addActionListener(new ActionListener()
620       {
621         @Override
622         public void actionPerformed(ActionEvent actionEvent)
623         {
624           all_actionPerformed();
625         }
626       });
627
628       this.setBorder(new TitledBorder(
629               MessageManager.getString("label.structures_filter")));
630       JvSwingUtils.jvInitComponent(this);
631
632       this.add(all);
633       this.add(alphaHelix);
634       this.add(betaStrand);
635       this.add(turn);
636     }
637
638     public void alphaHelix_actionPerformed()
639     {
640       updateSelectAllState();
641       aColChooser.setCurrentStructureFilterPanel(this);
642       aColChooser.updateView();
643     }
644
645     public void betaStrand_actionPerformed()
646     {
647       updateSelectAllState();
648       aColChooser.setCurrentStructureFilterPanel(this);
649       aColChooser.updateView();
650     }
651
652     public void turn_actionPerformed()
653     {
654       updateSelectAllState();
655       aColChooser.setCurrentStructureFilterPanel(this);
656       aColChooser.updateView();
657     }
658
659     public void all_actionPerformed()
660     {
661       if (all.isSelected())
662       {
663         alphaHelix.setSelected(true);
664         betaStrand.setSelected(true);
665         turn.setSelected(true);
666       }
667       else
668       {
669         alphaHelix.setSelected(false);
670         betaStrand.setSelected(false);
671         turn.setSelected(false);
672       }
673       aColChooser.setCurrentStructureFilterPanel(this);
674       aColChooser.updateView();
675     }
676
677     public void updateSelectAllState()
678     {
679       if (alphaHelix.isSelected() && betaStrand.isSelected()
680               && turn.isSelected())
681       {
682         all.setSelected(true);
683       }
684       else
685       {
686         all.setSelected(false);
687       }
688     }
689
690     public void syncState()
691     {
692       StructureFilterPanel sfp = aColChooser
693               .getCurrentStructureFilterPanel();
694       if (sfp != null)
695       {
696         alphaHelix.setSelected(sfp.alphaHelix.isSelected());
697         betaStrand.setSelected(sfp.betaStrand.isSelected());
698         turn.setSelected(sfp.turn.isSelected());
699         if (sfp.all.isSelected())
700         {
701           all.setSelected(true);
702           alphaHelix.setSelected(true);
703           betaStrand.setSelected(true);
704           turn.setSelected(true);
705         }
706       }
707
708     }
709   }
710
711   public class SearchPanel extends JPanel
712   {
713     private AnnotationColumnChooser aColChooser;
714
715     private JCheckBox displayName = new JCheckBox();
716
717     private JCheckBox description = new JCheckBox();
718
719     private static final String FILTER_BY_ANN_CACHE_KEY = "CACHE.SELECT_FILTER_BY_ANNOT";
720
721     public JvCacheableInputBox<String> searchBox = new JvCacheableInputBox<>(
722             FILTER_BY_ANN_CACHE_KEY, 23);
723
724     public SearchPanel(AnnotationColumnChooser aColChooser)
725     {
726
727       this.aColChooser = aColChooser;
728       JvSwingUtils.jvInitComponent(this);
729       this.setBorder(new TitledBorder(
730               MessageManager.getString("label.search_filter")));
731
732       searchBox.getComponent().setToolTipText(
733               MessageManager.getString("info.enter_search_text_here"));
734       searchBox.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.addFocusListener(new FocusAdapter()
747       {
748         @Override
749         public void focusLost(FocusEvent e)
750         {
751           searchStringAction();
752         }
753       });
754
755       JvSwingUtils.jvInitComponent(displayName, "label.label");
756       displayName.addActionListener(new ActionListener()
757       {
758         @Override
759         public void actionPerformed(ActionEvent actionEvent)
760         {
761           displayNameCheckboxAction();
762         }
763       });
764
765       JvSwingUtils.jvInitComponent(description, "label.description");
766       description.addActionListener(new ActionListener()
767       {
768         @Override
769         public void actionPerformed(ActionEvent actionEvent)
770         {
771           descriptionCheckboxAction();
772         }
773       });
774
775       syncState();
776       this.add(searchBox.getComponent());
777       this.add(displayName);
778       this.add(description);
779     }
780
781     public void displayNameCheckboxAction()
782     {
783       aColChooser.setCurrentSearchPanel(this);
784       aColChooser.updateView();
785     }
786
787     public void descriptionCheckboxAction()
788     {
789       aColChooser.setCurrentSearchPanel(this);
790       aColChooser.updateView();
791     }
792
793     public void searchStringAction()
794     {
795       aColChooser.setCurrentSearchPanel(this);
796       aColChooser.updateView();
797       updateSearchPanelToolTips();
798       searchBox.updateCache();
799     }
800
801     public void syncState()
802     {
803       SearchPanel sp = aColChooser.getCurrentSearchPanel();
804       if (sp != null)
805       {
806         description.setEnabled(sp.description.isEnabled());
807         description.setSelected(sp.description.isSelected());
808
809         displayName.setEnabled(sp.displayName.isEnabled());
810         displayName.setSelected(sp.displayName.isSelected());
811
812         searchBox.setSelectedItem(sp.searchBox.getUserInput());
813       }
814       updateSearchPanelToolTips();
815     }
816
817     public void updateSearchPanelToolTips()
818     {
819       String defaultTtip = MessageManager
820               .getString("info.enter_search_text_to_enable");
821       String labelTtip = MessageManager.formatMessage(
822               "info.search_in_annotation_label",
823               annotations.getSelectedItem().toString());
824       String descTtip = MessageManager.formatMessage(
825               "info.search_in_annotation_description",
826               annotations.getSelectedItem().toString());
827       displayName.setToolTipText(
828               displayName.isEnabled() ? labelTtip : defaultTtip);
829       description.setToolTipText(
830               description.isEnabled() ? descTtip : defaultTtip);
831     }
832   }
833
834   @Override
835   public void ok_actionPerformed()
836   {
837     saveCache();
838     super.ok_actionPerformed();
839   }
840
841   @Override
842   public void cancel_actionPerformed()
843   {
844     saveCache();
845     super.cancel_actionPerformed();
846   }
847
848   private void saveCache()
849   {
850     gSearchPanel.searchBox.persistCache();
851     ngSearchPanel.searchBox.persistCache();
852     gSearchPanel.searchBox.updateCache();
853     ngSearchPanel.searchBox.updateCache();
854   }
855 }