JAL-3161 limit tooltip and status updates to visible columns
[jalview.git] / src / jalview / appletgui / FeatureSettings.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 package jalview.appletgui;
22
23 import jalview.api.FeatureColourI;
24 import jalview.api.FeatureSettingsControllerI;
25 import jalview.datamodel.AlignmentI;
26 import jalview.datamodel.SequenceI;
27 import jalview.util.MessageManager;
28 import jalview.viewmodel.seqfeatures.FeatureRendererModel.FeatureSettingsBean;
29
30 import java.awt.BorderLayout;
31 import java.awt.Button;
32 import java.awt.Checkbox;
33 import java.awt.Color;
34 import java.awt.Component;
35 import java.awt.Dimension;
36 import java.awt.Font;
37 import java.awt.FontMetrics;
38 import java.awt.Frame;
39 import java.awt.Graphics;
40 import java.awt.GridLayout;
41 import java.awt.Image;
42 import java.awt.Label;
43 import java.awt.MenuItem;
44 import java.awt.Panel;
45 import java.awt.PopupMenu;
46 import java.awt.ScrollPane;
47 import java.awt.Scrollbar;
48 import java.awt.event.ActionEvent;
49 import java.awt.event.ActionListener;
50 import java.awt.event.AdjustmentEvent;
51 import java.awt.event.AdjustmentListener;
52 import java.awt.event.InputEvent;
53 import java.awt.event.ItemEvent;
54 import java.awt.event.ItemListener;
55 import java.awt.event.MouseEvent;
56 import java.awt.event.MouseListener;
57 import java.awt.event.MouseMotionListener;
58 import java.awt.event.WindowAdapter;
59 import java.awt.event.WindowEvent;
60 import java.util.ArrayList;
61 import java.util.Arrays;
62 import java.util.HashSet;
63 import java.util.List;
64 import java.util.Map;
65 import java.util.Set;
66
67 public class FeatureSettings extends Panel
68         implements ItemListener, MouseListener, MouseMotionListener,
69         AdjustmentListener, FeatureSettingsControllerI
70 {
71   FeatureRenderer fr;
72
73   AlignmentPanel ap;
74
75   AlignViewport av;
76
77   Frame frame;
78
79   Panel groupPanel;
80
81   Panel featurePanel = new Panel();
82
83   ScrollPane scrollPane;
84
85   Image linkImage;
86
87   Scrollbar transparency;
88
89   public FeatureSettings(final AlignmentPanel ap)
90   {
91     this.ap = ap;
92     this.av = ap.av;
93     ap.av.featureSettings = this;
94     fr = ap.seqPanel.seqCanvas.getFeatureRenderer();
95
96     transparency = new Scrollbar(Scrollbar.HORIZONTAL,
97             100 - (int) (fr.getTransparency() * 100), 1, 1, 100);
98
99     transparency.addAdjustmentListener(this);
100
101     java.net.URL url = getClass().getResource("/images/link.gif");
102     if (url != null)
103     {
104       linkImage = java.awt.Toolkit.getDefaultToolkit().getImage(url);
105     }
106
107     if (av.isShowSequenceFeatures() || !fr.hasRenderOrder())
108     {
109       fr.findAllFeatures(true); // was default - now true to make all visible
110     }
111     groupPanel = new Panel();
112
113     discoverAllFeatureData();
114
115     this.setLayout(new BorderLayout());
116     scrollPane = new ScrollPane();
117     scrollPane.add(featurePanel);
118     if (fr.getAllFeatureColours() != null
119             && fr.getAllFeatureColours().size() > 0)
120     {
121       add(scrollPane, BorderLayout.CENTER);
122     }
123
124     Button invert = new Button(
125             MessageManager.getString("label.invert_selection"));
126     invert.addActionListener(new ActionListener()
127     {
128
129       @Override
130       public void actionPerformed(ActionEvent e)
131       {
132         invertSelection();
133       }
134     });
135
136     Panel lowerPanel = new Panel(new GridLayout(2, 1, 5, 10));
137     lowerPanel.add(invert);
138
139     Panel tPanel = new Panel(new BorderLayout());
140
141     tPanel.add(transparency, BorderLayout.CENTER);
142     tPanel.add(new Label("Transparency"), BorderLayout.EAST);
143
144     lowerPanel.add(tPanel, BorderLayout.SOUTH);
145
146     add(lowerPanel, BorderLayout.SOUTH);
147
148     groupPanel.setLayout(
149             new GridLayout((fr.getFeatureGroupsSize()) / 4 + 1, 4)); // JBPNote
150                                                                      // - this
151                                                                      // was
152                                                                      // scaled
153                                                                      // on
154                                                                      // number
155                                                                      // of
156                                                                      // visible
157                                                                      // groups.
158                                                                      // seems
159                                                                      // broken
160     groupPanel.validate();
161
162     add(groupPanel, BorderLayout.NORTH);
163
164     frame = new Frame();
165     frame.add(this);
166     final FeatureSettings me = this;
167     frame.addWindowListener(new WindowAdapter()
168     {
169       @Override
170       public void windowClosing(WindowEvent e)
171       {
172         if (me.av.featureSettings == me)
173         {
174           me.av.featureSettings = null;
175           me.ap = null;
176           me.av = null;
177         }
178       }
179     });
180     int height = featurePanel.getComponentCount() * 50 + 60;
181
182     height = Math.max(200, height);
183     height = Math.min(400, height);
184     int width = 300;
185     jalview.bin.JalviewLite.addFrame(frame,
186             MessageManager.getString("label.sequence_feature_settings"),
187             width, height);
188   }
189
190   @Override
191   public void paint(Graphics g)
192   {
193     g.setColor(Color.black);
194     g.drawString(MessageManager.getString(
195             "label.no_features_added_to_this_alignment"), 10, 20);
196     g.drawString(MessageManager.getString(
197             "label.features_can_be_added_from_searches_1"), 10, 40);
198     g.drawString(MessageManager.getString(
199             "label.features_can_be_added_from_searches_2"), 10, 60);
200   }
201
202   protected void popupSort(final MyCheckbox check,
203           final Map<String, float[][]> minmax, int x, int y)
204   {
205     final String type = check.type;
206     final FeatureColourI typeCol = fr.getFeatureStyle(type);
207     PopupMenu men = new PopupMenu(MessageManager
208             .formatMessage("label.settings_for_type", new String[]
209             { type }));
210     java.awt.MenuItem scr = new MenuItem(
211             MessageManager.getString("label.sort_by_score"));
212     men.add(scr);
213     final FeatureSettings me = this;
214     scr.addActionListener(new ActionListener()
215     {
216
217       @Override
218       public void actionPerformed(ActionEvent e)
219       {
220         me.ap.alignFrame.avc
221                 .sortAlignmentByFeatureScore(Arrays.asList(new String[]
222                 { type }));
223       }
224
225     });
226     MenuItem dens = new MenuItem(
227             MessageManager.getString("label.sort_by_density"));
228     dens.addActionListener(new ActionListener()
229     {
230
231       @Override
232       public void actionPerformed(ActionEvent e)
233       {
234         me.ap.alignFrame.avc
235                 .sortAlignmentByFeatureDensity(Arrays.asList(new String[]
236                 { type }));
237       }
238
239     });
240     men.add(dens);
241
242     if (minmax != null)
243     {
244       final float[][] typeMinMax = minmax.get(type);
245       /*
246        * final java.awt.CheckboxMenuItem chb = new
247        * java.awt.CheckboxMenuItem("Vary Height"); // this is broken at the
248        * moment chb.setState(minmax.get(type) != null);
249        * chb.addActionListener(new ActionListener() {
250        * 
251        * public void actionPerformed(ActionEvent e) {
252        * chb.setState(chb.getState()); if (chb.getState()) { minmax.put(type,
253        * null); } else { minmax.put(type, typeMinMax); } }
254        * 
255        * }); men.add(chb);
256        */
257       if (typeMinMax != null && typeMinMax[0] != null)
258       {
259         // graduated colourschemes for those where minmax exists for the
260         // positional features
261         MenuItem mxcol = new MenuItem(
262                 (typeCol.isSimpleColour()) ? "Graduated Colour"
263                         : "Single Colour");
264         men.add(mxcol);
265         mxcol.addActionListener(new ActionListener()
266         {
267
268           @Override
269           public void actionPerformed(ActionEvent e)
270           {
271             if (typeCol.isSimpleColour())
272             {
273               new FeatureColourChooser(me, type);
274               // write back the current colour object to update the table
275               check.updateColor(fr.getFeatureStyle(type));
276             }
277             else
278             {
279               new UserDefinedColours(me, check.type, typeCol);
280             }
281           }
282
283         });
284       }
285     }
286
287     MenuItem selectContaining = new MenuItem(
288             MessageManager.getString("label.select_columns_containing"));
289     selectContaining.addActionListener(new ActionListener()
290     {
291       @Override
292       public void actionPerformed(ActionEvent e)
293       {
294         me.ap.alignFrame.avc.markColumnsContainingFeatures(false, false,
295                 false, type);
296       }
297     });
298     men.add(selectContaining);
299
300     MenuItem selectNotContaining = new MenuItem(MessageManager
301             .getString("label.select_columns_not_containing"));
302     selectNotContaining.addActionListener(new ActionListener()
303     {
304       @Override
305       public void actionPerformed(ActionEvent e)
306       {
307         me.ap.alignFrame.avc.markColumnsContainingFeatures(true, false,
308                 false, type);
309       }
310     });
311     men.add(selectNotContaining);
312
313     MenuItem hideContaining = new MenuItem(
314             MessageManager.getString("label.hide_columns_containing"));
315     hideContaining.addActionListener(new ActionListener()
316     {
317       @Override
318       public void actionPerformed(ActionEvent e)
319       {
320         hideFeatureColumns(type, true);
321       }
322     });
323     men.add(hideContaining);
324
325     MenuItem hideNotContaining = new MenuItem(
326             MessageManager.getString("label.hide_columns_not_containing"));
327     hideNotContaining.addActionListener(new ActionListener()
328     {
329       @Override
330       public void actionPerformed(ActionEvent e)
331       {
332         hideFeatureColumns(type, false);
333       }
334     });
335     men.add(hideNotContaining);
336
337     this.featurePanel.add(men);
338     men.show(this.featurePanel, x, y);
339   }
340
341   @Override
342   public void discoverAllFeatureData()
343   {
344     if (fr.getAllFeatureColours() != null
345             && fr.getAllFeatureColours().size() > 0)
346     {
347       // rebuildGroups();
348
349     }
350     resetTable(false);
351   }
352
353   /**
354    * Answers the visibility of the given group, and adds a checkbox for it if
355    * there is not one already
356    */
357   public boolean checkGroupState(String group)
358   {
359     boolean visible = fr.checkGroupVisibility(group, true);
360
361     /*
362      * is there already a checkbox for this group?
363      */
364     for (int g = 0; g < groupPanel.getComponentCount(); g++)
365     {
366       if (((Checkbox) groupPanel.getComponent(g)).getLabel().equals(group))
367       {
368         ((Checkbox) groupPanel.getComponent(g)).setState(visible);
369         return visible;
370       }
371     }
372
373     /*
374      * add a new checkbox
375      */
376     Checkbox check = new MyCheckbox(group, visible, false);
377     check.addMouseListener(this);
378     check.setFont(new Font("Serif", Font.BOLD, 12));
379     check.addItemListener(groupItemListener);
380     groupPanel.add(check);
381
382     groupPanel.validate();
383     return visible;
384   }
385
386   // This routine adds and removes checkboxes depending on
387   // Group selection states
388   void resetTable(boolean groupsChanged)
389   {
390     List<String> displayableTypes = new ArrayList<>();
391     Set<String> foundGroups = new HashSet<>();
392
393     AlignmentI alignment = av.getAlignment();
394
395     for (int i = 0; i < alignment.getHeight(); i++)
396     {
397       SequenceI seq = alignment.getSequenceAt(i);
398
399       /*
400        * get the sequence's groups for positional features
401        * and keep track of which groups are visible
402        */
403       Set<String> groups = seq.getFeatures().getFeatureGroups(true);
404       Set<String> visibleGroups = new HashSet<>();
405       for (String group : groups)
406       {
407         // if (group == null || fr.checkGroupVisibility(group, true))
408         if (group == null || checkGroupState(group))
409         {
410           visibleGroups.add(group);
411         }
412       }
413       foundGroups.addAll(groups);
414
415       /*
416        * get distinct feature types for visible groups
417        * record distinct visible types
418        */
419       Set<String> types = seq.getFeatures().getFeatureTypesForGroups(true,
420               visibleGroups.toArray(new String[visibleGroups.size()]));
421       displayableTypes.addAll(types);
422     }
423
424     /*
425      * remove any checkboxes for groups not present
426      */
427     pruneGroups(foundGroups);
428
429     Component[] comps;
430     int cSize = featurePanel.getComponentCount();
431     MyCheckbox check;
432     // This will remove any checkboxes which shouldn't be
433     // visible
434     for (int i = 0; i < cSize; i++)
435     {
436       comps = featurePanel.getComponents();
437       check = (MyCheckbox) comps[i];
438       if (!displayableTypes.contains(check.type))
439       {
440         featurePanel.remove(i);
441         cSize--;
442         i--;
443       }
444     }
445
446     if (fr.getRenderOrder() != null)
447     {
448       // First add the checks in the previous render order,
449       // in case the window has been closed and reopened
450       List<String> rol = fr.getRenderOrder();
451       for (int ro = rol.size() - 1; ro > -1; ro--)
452       {
453         String item = rol.get(ro);
454
455         if (!displayableTypes.contains(item))
456         {
457           continue;
458         }
459
460         displayableTypes.remove(item);
461
462         addCheck(false, item);
463       }
464     }
465
466     /*
467      * now add checkboxes which should be visible,
468      * if they have not already been added
469      */
470     for (String type : displayableTypes)
471     {
472       addCheck(groupsChanged, type);
473     }
474
475     featurePanel.setLayout(
476             new GridLayout(featurePanel.getComponentCount(), 1, 10, 5));
477     featurePanel.validate();
478
479     if (scrollPane != null)
480     {
481       scrollPane.validate();
482     }
483
484     itemStateChanged(null);
485   }
486
487   /**
488    * Remove from the groups panel any checkboxes for groups that are not in the
489    * foundGroups set. This enables removing a group from the display when the
490    * last feature in that group is deleted.
491    * 
492    * @param foundGroups
493    */
494   protected void pruneGroups(Set<String> foundGroups)
495   {
496     for (int g = 0; g < groupPanel.getComponentCount(); g++)
497     {
498       Checkbox checkbox = (Checkbox) groupPanel.getComponent(g);
499       if (!foundGroups.contains(checkbox.getLabel()))
500       {
501         groupPanel.remove(checkbox);
502       }
503     }
504   }
505
506   /**
507    * update the checklist of feature types with the given type
508    * 
509    * @param groupsChanged
510    *          true means if the type is not in the display list then it will be
511    *          added and displayed
512    * @param type
513    *          feature type to be checked for in the list.
514    */
515   void addCheck(boolean groupsChanged, String type)
516   {
517     boolean addCheck;
518     Component[] comps = featurePanel.getComponents();
519     MyCheckbox check;
520     addCheck = true;
521     for (int i = 0; i < featurePanel.getComponentCount(); i++)
522     {
523       check = (MyCheckbox) comps[i];
524       if (check.type.equals(type))
525       {
526         addCheck = false;
527         break;
528       }
529     }
530
531     if (addCheck)
532     {
533       boolean selected = false;
534       if (groupsChanged || av.getFeaturesDisplayed().isVisible(type))
535       {
536         selected = true;
537       }
538
539       check = new MyCheckbox(type, selected, false,
540               fr.getFeatureStyle(type));
541
542       check.addMouseListener(this);
543       check.addMouseMotionListener(this);
544       check.addItemListener(this);
545       if (groupsChanged)
546       {
547         // add at beginning of stack.
548         featurePanel.add(check, 0);
549       }
550       else
551       {
552         // add at end of stack.
553         featurePanel.add(check);
554       }
555     }
556   }
557
558   protected void invertSelection()
559   {
560     for (int i = 0; i < featurePanel.getComponentCount(); i++)
561     {
562       Checkbox check = (Checkbox) featurePanel.getComponent(i);
563       check.setState(!check.getState());
564     }
565     selectionChanged(true);
566   }
567
568   private ItemListener groupItemListener = new ItemListener()
569   {
570     @Override
571     public void itemStateChanged(ItemEvent evt)
572     {
573       Checkbox source = (Checkbox) evt.getSource();
574       fr.setGroupVisibility(source.getLabel(), source.getState());
575       ap.seqPanel.seqCanvas.repaint();
576       if (ap.overviewPanel != null)
577       {
578         ap.overviewPanel.updateOverviewImage();
579       }
580       resetTable(true);
581       return;
582     };
583   };
584
585   @Override
586   public void itemStateChanged(ItemEvent evt)
587   {
588     selectionChanged(true);
589   }
590
591   void selectionChanged(boolean updateOverview)
592   {
593     Component[] comps = featurePanel.getComponents();
594     int cSize = comps.length;
595     FeatureSettingsBean[] rowData = new FeatureSettingsBean[cSize];
596     int i = 0;
597     for (Component comp : comps)
598     {
599       MyCheckbox check = (MyCheckbox) comp;
600       // feature filter set to null as not (yet) offered in applet
601       FeatureColourI colour = fr.getFeatureStyle(check.type);
602       rowData[i] = new FeatureSettingsBean(check.type, colour, null,
603               check.getState());
604       i++;
605     }
606
607     fr.setFeaturePriority(rowData);
608
609     ap.paintAlignment(updateOverview, updateOverview);
610   }
611
612   MyCheckbox selectedCheck;
613
614   boolean dragging = false;
615
616   @Override
617   public void mouseDragged(MouseEvent evt)
618   {
619     if (((Component) evt.getSource()).getParent() != featurePanel)
620     {
621       return;
622     }
623     dragging = true;
624   }
625
626   @Override
627   public void mouseReleased(MouseEvent evt)
628   {
629     if (((Component) evt.getSource()).getParent() != featurePanel)
630     {
631       return;
632     }
633
634     Component comp = null;
635     Checkbox target = null;
636
637     int height = evt.getY() + evt.getComponent().getLocation().y;
638
639     if (height > featurePanel.getSize().height)
640     {
641
642       comp = featurePanel
643               .getComponent(featurePanel.getComponentCount() - 1);
644     }
645     else if (height < 0)
646     {
647       comp = featurePanel.getComponent(0);
648     }
649     else
650     {
651       comp = featurePanel.getComponentAt(evt.getX(),
652               evt.getY() + evt.getComponent().getLocation().y);
653     }
654
655     if (comp != null && comp instanceof Checkbox)
656     {
657       target = (Checkbox) comp;
658     }
659
660     if (selectedCheck != null && target != null && selectedCheck != target)
661     {
662       int targetIndex = -1;
663       for (int i = 0; i < featurePanel.getComponentCount(); i++)
664       {
665         if (target == featurePanel.getComponent(i))
666         {
667           targetIndex = i;
668           break;
669         }
670       }
671
672       featurePanel.remove(selectedCheck);
673       featurePanel.add(selectedCheck, targetIndex);
674       featurePanel.validate();
675       itemStateChanged(null);
676     }
677   }
678
679   public void setUserColour(String feature, FeatureColourI originalColour)
680   {
681     fr.setColour(feature, originalColour);
682     refreshTable();
683   }
684
685   public void refreshTable()
686   {
687     featurePanel.removeAll();
688     resetTable(false);
689     ap.paintAlignment(true, true);
690   }
691
692   @Override
693   public void mouseEntered(MouseEvent evt)
694   {
695   }
696
697   @Override
698   public void mouseExited(MouseEvent evt)
699   {
700   }
701
702   @Override
703   public void mouseClicked(MouseEvent evt)
704   {
705     MyCheckbox check = (MyCheckbox) evt.getSource();
706     if ((evt.getModifiers() & InputEvent.BUTTON3_MASK) != 0)
707     {
708       this.popupSort(check, fr.getMinMax(), evt.getX(), evt.getY());
709     }
710
711     if (check.getParent() != featurePanel)
712     {
713       return;
714     }
715
716     if (evt.getClickCount() > 1)
717     {
718       FeatureColourI fcol = fr.getFeatureStyle(check.type);
719       if (fcol.isSimpleColour())
720       {
721         new UserDefinedColours(this, check.type, fcol.getColour());
722       }
723       else
724       {
725         new FeatureColourChooser(this, check.type);
726         // write back the current colour object to update the table
727         check.updateColor(fr.getFeatureStyle(check.type));
728       }
729     }
730   }
731
732   @Override
733   public void mouseMoved(MouseEvent evt)
734   {
735   }
736
737   @Override
738   public void adjustmentValueChanged(AdjustmentEvent evt)
739   {
740     fr.setTransparency((100 - transparency.getValue()) / 100f);
741     ap.paintAlignment(true, true);
742   }
743
744   class MyCheckbox extends Checkbox
745   {
746     public String type;
747
748     public int stringWidth;
749
750     boolean hasLink;
751
752     FeatureColourI col;
753
754     public void updateColor(FeatureColourI newcol)
755     {
756       col = newcol;
757       if (col.isSimpleColour())
758       {
759         setBackground(col.getColour());
760       }
761       else
762       {
763         String vlabel = type;
764         if (col.isAboveThreshold())
765         {
766           vlabel += " (>)";
767         }
768         else if (col.isBelowThreshold())
769         {
770           vlabel += " (<)";
771         }
772         if (col.isColourByLabel())
773         {
774           setBackground(Color.white);
775           vlabel += " (by Label)";
776         }
777         else
778         {
779           setBackground(col.getMinColour());
780         }
781         this.setLabel(vlabel);
782       }
783       repaint();
784     }
785
786     public MyCheckbox(String label, boolean checked, boolean haslink)
787     {
788       super(label, checked);
789       type = label;
790       FontMetrics fm = av.nullFrame.getFontMetrics(av.nullFrame.getFont());
791       stringWidth = fm.stringWidth(label);
792       this.hasLink = haslink;
793     }
794
795     public MyCheckbox(String type, boolean selected, boolean b,
796             FeatureColourI featureStyle)
797     {
798       this(type, selected, b);
799       updateColor(featureStyle);
800     }
801
802     @Override
803     public void paint(Graphics g)
804     {
805       Dimension d = getSize();
806       if (col != null)
807       {
808         if (col.isColourByLabel())
809         {
810           g.setColor(Color.white);
811           g.fillRect(d.width / 2, 0, d.width / 2, d.height);
812           /*
813            * g.setColor(Color.black); Font f=g.getFont().deriveFont(9);
814            * g.setFont(f);
815            * 
816            * // g.setFont(g.getFont().deriveFont( //
817            * AffineTransform.getScaleInstance( //
818            * width/g.getFontMetrics().stringWidth("Label"), //
819            * height/g.getFontMetrics().getHeight()))); g.drawString("Label",
820            * width/2, 0);
821            */
822
823         }
824         else if (col.isGraduatedColour())
825         {
826           Color maxCol = col.getMaxColour();
827           g.setColor(maxCol);
828           g.fillRect(d.width / 2, 0, d.width / 2, d.height);
829
830         }
831       }
832
833       if (hasLink)
834       {
835         g.drawImage(linkImage, stringWidth + 25,
836                 (getSize().height - linkImage.getHeight(this)) / 2, this);
837       }
838     }
839   }
840
841   /**
842    * Hide columns containing (or not containing) a given feature type
843    * 
844    * @param type
845    * @param columnsContaining
846    */
847   void hideFeatureColumns(final String type, boolean columnsContaining)
848   {
849     if (ap.alignFrame.avc.markColumnsContainingFeatures(columnsContaining,
850             false, false, type))
851     {
852       if (ap.alignFrame.avc.markColumnsContainingFeatures(
853               !columnsContaining, false, false, type))
854       {
855         ap.alignFrame.viewport.hideSelectedColumns();
856       }
857     }
858   }
859
860   @Override
861   public void mousePressed(MouseEvent e)
862   {
863     // TODO Auto-generated method stub
864
865   }
866
867 }