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