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