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