DAS feature retrieval updated
[jalview.git] / src / jalview / gui / FeatureSettings.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer\r
3  * Copyright (C) 2005 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
4  *\r
5  * This program is free software; you can redistribute it and/or\r
6  * modify it under the terms of the GNU General Public License\r
7  * as published by the Free Software Foundation; either version 2\r
8  * of the License, or (at your option) any later version.\r
9  *\r
10  * This program is distributed in the hope that it will be useful,\r
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13  * GNU General Public License for more details.\r
14  *\r
15  * You should have received a copy of the GNU General Public License\r
16  * along with this program; if not, write to the Free Software\r
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA\r
18  */\r
19 package jalview.gui;\r
20 \r
21 import jalview.datamodel.*;\r
22 import javax.swing.*;\r
23 import javax.swing.event.*;\r
24 import java.awt.*;\r
25 import java.util.*;\r
26 import javax.swing.BorderFactory;\r
27 import java.awt.event.*;\r
28 import javax.swing.table.*;\r
29 import java.io.*;\r
30 import jalview.io.JalviewFileChooser;\r
31 import java.awt.BorderLayout;\r
32 import java.awt.Font;\r
33 import java.awt.Color;\r
34 import org.biojava.dasobert.dasregistry.DasSource;\r
35 import org.biojava.dasobert.dasregistry.DasCoordinateSystem;\r
36 \r
37 public class FeatureSettings extends JPanel\r
38 {\r
39   DasSourceBrowser dassourceBrowser;\r
40   JPanel settingsPane = new JPanel();\r
41   JPanel dasSettingsPane = new JPanel();\r
42 \r
43   final FeatureRenderer fr;\r
44   final AlignFrame af;\r
45   Object [][] originalData;\r
46   final JInternalFrame frame;\r
47   JScrollPane scrollPane = new JScrollPane();\r
48   JTable table;\r
49   JPanel groupPanel;\r
50   JSlider transparency = new JSlider();\r
51 \r
52   JPanel transPanel = new JPanel(new FlowLayout());\r
53   boolean alignmentHasFeatures = false;\r
54 \r
55   public FeatureSettings(AlignFrame af)\r
56   {\r
57     this.af = af;\r
58     fr = af.getFeatureRenderer();\r
59 \r
60     transparency.setMaximum( 100 - (int)(fr.transparency*100) ) ;\r
61 \r
62    try\r
63    {\r
64      jbInit();\r
65    }\r
66    catch (Exception ex)\r
67    {\r
68      ex.printStackTrace();\r
69    }\r
70 \r
71     dassourceBrowser = new DasSourceBrowser();\r
72     dasSettingsPane.add(dassourceBrowser, BorderLayout.CENTER);\r
73 \r
74 \r
75 \r
76     if (af.getViewport().featuresDisplayed == null || fr.renderOrder==null)\r
77        fr.findAllFeatures();\r
78 \r
79 \r
80     setTableData();\r
81 \r
82     frame = new JInternalFrame();\r
83     frame.setContentPane(this);\r
84     Desktop.addInternalFrame(frame, "Sequence Feature Settings", 400, 450);\r
85     frame.setLayer(JLayeredPane.PALETTE_LAYER);\r
86   }\r
87 \r
88   public void setTableData()\r
89   {\r
90     alignmentHasFeatures = false;\r
91 \r
92     if (fr.featureGroups == null)\r
93       fr.featureGroups = new Hashtable();\r
94 \r
95     Vector allFeatures = new Vector();\r
96     Vector allGroups = new Vector();\r
97     SequenceFeature[] tmpfeatures;\r
98     String group;\r
99 \r
100     for (int i = 0; i < af.getViewport().alignment.getHeight(); i++)\r
101     {\r
102       if (af.getViewport().alignment.getSequenceAt(i).getDatasetSequence().getSequenceFeatures() == null)\r
103         continue;\r
104 \r
105       alignmentHasFeatures = true;\r
106 \r
107       tmpfeatures = af.getViewport().alignment.getSequenceAt(i).getDatasetSequence().getSequenceFeatures();\r
108 \r
109       int index = 0;\r
110       while (index < tmpfeatures.length)\r
111       {\r
112         if(tmpfeatures[index].begin == 0 && tmpfeatures[index].end ==0)\r
113         {\r
114           index++;\r
115           continue;\r
116         }\r
117 \r
118         if(tmpfeatures[index].getFeatureGroup()!=null)\r
119         {\r
120           group = tmpfeatures[index].featureGroup;\r
121           if(!allGroups.contains(group))\r
122            {\r
123              allGroups.addElement(group);\r
124 \r
125              boolean visible = true;\r
126              if (fr.featureGroups.containsKey(group))\r
127              {\r
128                visible = ( (Boolean) fr.featureGroups.get(group)).booleanValue();\r
129              }\r
130              else\r
131              {\r
132                fr.featureGroups.put(group, new Boolean(visible));\r
133                if (groupPanel == null)\r
134                {\r
135                  groupPanel = new JPanel();\r
136                }\r
137 \r
138                final JCheckBox check = new JCheckBox(group, visible);\r
139                check.setFont(new Font("Serif", Font.BOLD, 12));\r
140                check.addItemListener(new ItemListener()\r
141                {\r
142                  public void itemStateChanged(ItemEvent evt)\r
143                  {\r
144                    fr.featureGroups.put(check.getText(),\r
145                                         new Boolean(check.isSelected()));\r
146                    af.alignPanel.seqPanel.seqCanvas.repaint();\r
147                    if (af.alignPanel.overviewPanel != null)\r
148                      af.alignPanel.overviewPanel.updateOverviewImage();\r
149 \r
150                    resetTable(true);\r
151                  }\r
152                });\r
153                groupPanel.add(check);\r
154              }\r
155            }\r
156 \r
157        }\r
158 \r
159        if (!allFeatures.contains(tmpfeatures[index].getType()))\r
160        {\r
161            allFeatures.addElement(tmpfeatures[index].getType());\r
162        }\r
163        index ++;\r
164     }\r
165   }\r
166 \r
167 \r
168     if(!alignmentHasFeatures)\r
169      {\r
170     //   try\r
171      //  { frame.setClosed(true);  }\r
172     //   catch (Exception ex){}\r
173 \r
174     //   JOptionPane.showInternalMessageDialog(\r
175     ///       Desktop.desktop, "No features have been added to this alignment!",\r
176     //\r
177    //    return;\r
178      }\r
179 \r
180      resetTable(false);\r
181   }\r
182 \r
183 \r
184   void resetTable(boolean groupsChanged)\r
185   {\r
186    SequenceFeature [] tmpfeatures;\r
187    String group=null, type;\r
188    Vector visibleChecks = new Vector();\r
189 \r
190    //Find out which features should be visible depending on which groups\r
191    //are selected / deselected\r
192     for (int i = 0; i < af.getViewport().alignment.getHeight(); i++)\r
193     {\r
194 \r
195         tmpfeatures = af.getViewport().alignment.getSequenceAt(i).getDatasetSequence().getSequenceFeatures();\r
196         if (tmpfeatures == null)\r
197           continue;\r
198 \r
199         int index = 0;\r
200         while (index < tmpfeatures.length)\r
201         {\r
202           group = tmpfeatures[index].featureGroup;\r
203 \r
204           if(tmpfeatures[index].begin==0 && tmpfeatures[index].end==0)\r
205           {\r
206             index ++;\r
207             continue;\r
208           }\r
209 \r
210           if (group==null || fr.featureGroups.get(group)==null ||\r
211               ((Boolean) fr.featureGroups.get(group)).booleanValue())\r
212           {\r
213             type = tmpfeatures[index].getType();\r
214             if(!visibleChecks.contains(type) )\r
215             {\r
216               visibleChecks.addElement(type);\r
217             }\r
218           }\r
219           index++;\r
220         }\r
221     }\r
222 \r
223     int fSize = visibleChecks.size();\r
224     Object [][] data = new Object[fSize][3];\r
225     int dataIndex = 0;\r
226 \r
227     if(fr.renderOrder!=null)\r
228     {\r
229       //First add the checks in the previous render order,\r
230       //in case the window has been closed and reopened\r
231       for(int ro=fr.renderOrder.length-1; ro>-1; ro--)\r
232       {\r
233            type = fr.renderOrder[ro];\r
234 \r
235            if(!visibleChecks.contains(type))\r
236              continue;\r
237 \r
238            data[dataIndex][0] = type;\r
239            data[dataIndex][1] = fr.getColour(type);\r
240            data[dataIndex][2] = new Boolean(af.getViewport().featuresDisplayed.containsKey(type));\r
241            dataIndex++;\r
242            visibleChecks.removeElement(type);\r
243       }\r
244     }\r
245 \r
246     fSize = visibleChecks.size();\r
247     for(int i=0; i<fSize; i++)\r
248     {\r
249       //These must be extra features belonging to the group\r
250       //which was just selected\r
251       type = visibleChecks.elementAt(i).toString();\r
252       data[dataIndex][0] = type;\r
253 \r
254       data[dataIndex][1] = fr.getColour(type);\r
255       data[dataIndex][2] = new Boolean(true);\r
256       dataIndex++;\r
257     }\r
258 \r
259     if(originalData==null)\r
260     {\r
261       originalData = new Object[data.length][3];\r
262       System.arraycopy(data,0,originalData,0,data.length);\r
263     }\r
264 \r
265     table = new JTable(new FeatureTableModel(data));\r
266     scrollPane.setViewportView(table);\r
267     table.getTableHeader().setFont(new Font("Verdana", Font.PLAIN, 12));\r
268     table.setFont(new Font("Verdana", Font.PLAIN, 12));\r
269     table.setDefaultRenderer(Color.class,\r
270                          new ColorRenderer());\r
271 \r
272     table.setDefaultEditor(Color.class,\r
273                       new ColorEditor());\r
274 \r
275     table.getColumnModel().getColumn(0).setPreferredWidth(200);\r
276 \r
277     table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);\r
278 \r
279     table.addMouseListener(new MouseAdapter()\r
280         {\r
281           public void mousePressed(MouseEvent evt)\r
282           {\r
283             selectedRow = table.rowAtPoint(evt.getPoint());\r
284           }\r
285         });\r
286 \r
287     table.addMouseMotionListener(new MouseMotionAdapter()\r
288         {\r
289           public void mouseDragged(MouseEvent evt)\r
290           {\r
291             int newRow = table.rowAtPoint(evt.getPoint());\r
292             if(newRow!=selectedRow\r
293                && selectedRow!=-1\r
294                && newRow!=-1)\r
295             {\r
296               Object[] temp = new Object[3];\r
297               temp[0] = table.getValueAt(selectedRow, 0);\r
298               temp[1] = table.getValueAt(selectedRow, 1);\r
299               temp[2] = table.getValueAt(selectedRow, 2);\r
300 \r
301               table.setValueAt(table.getValueAt(newRow, 0), selectedRow, 0);\r
302               table.setValueAt(table.getValueAt(newRow, 1), selectedRow, 1);\r
303               table.setValueAt(table.getValueAt(newRow, 2), selectedRow, 2);\r
304 \r
305               table.setValueAt(temp[0], newRow, 0);\r
306               table.setValueAt(temp[1], newRow, 1);\r
307               table.setValueAt(temp[2], newRow, 2);\r
308 \r
309               selectedRow = newRow;\r
310             }\r
311           }\r
312     });\r
313 \r
314     if (groupPanel != null)\r
315     {\r
316       groupPanel.setLayout(\r
317           new GridLayout(fr.featureGroups.size() / 4 + 1, 4));\r
318 \r
319       groupPanel.validate();\r
320       bigPanel.add(groupPanel, BorderLayout.NORTH);\r
321     }\r
322 \r
323     updateFeatureRenderer(data);\r
324 \r
325   }\r
326 \r
327   void load()\r
328   {\r
329     JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.getProperty(\r
330                  "LAST_DIRECTORY"), new String[] { "fc" },\r
331              new String[] { "Sequence Feature Colours" }, "Sequence Feature Colours");\r
332      chooser.setFileView(new jalview.io.JalviewFileView());\r
333      chooser.setDialogTitle("Load Feature Colours");\r
334      chooser.setToolTipText("Load");\r
335 \r
336      int value = chooser.showOpenDialog(this);\r
337 \r
338      if (value == JalviewFileChooser.APPROVE_OPTION)\r
339      {\r
340        File file = chooser.getSelectedFile();\r
341 \r
342        try\r
343        {\r
344          InputStreamReader in = new InputStreamReader(new FileInputStream(\r
345              file), "UTF-8");\r
346 \r
347          jalview.binding.JalviewUserColours jucs = new jalview.binding.\r
348              JalviewUserColours();\r
349          jucs = (jalview.binding.JalviewUserColours) jucs.unmarshal(in);\r
350 \r
351 \r
352          for (int i = 0; i < jucs.getColourCount(); i++)\r
353          {\r
354            fr.setColour( jucs.getColour(i).getName(),\r
355                           new Color(Integer.parseInt( jucs.getColour(i).getRGB(), 16)));\r
356          }\r
357 \r
358          setTableData();\r
359          af.alignPanel.repaint();\r
360        }\r
361        catch (Exception ex)\r
362        {\r
363          System.out.println("Error loading User Colour File\n" + ex);\r
364        }\r
365      }\r
366   }\r
367 \r
368   void save()\r
369   {\r
370     JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.getProperty(\r
371                 "LAST_DIRECTORY"), new String[] { "fc" },\r
372             new String[] { "Sequence Feature Colours" }, "Sequence Feature Colours");\r
373     chooser.setFileView(new jalview.io.JalviewFileView());\r
374     chooser.setDialogTitle("Save Feature Colour Scheme");\r
375     chooser.setToolTipText("Save");\r
376 \r
377     int value = chooser.showSaveDialog(this);\r
378 \r
379     if (value == JalviewFileChooser.APPROVE_OPTION)\r
380     {\r
381         String choice = chooser.getSelectedFile().getPath();\r
382         jalview.binding.JalviewUserColours ucs = new jalview.binding.JalviewUserColours();\r
383         ucs.setSchemeName("Sequence Features");\r
384         try\r
385         {\r
386             PrintWriter out = new PrintWriter(new OutputStreamWriter(\r
387                         new FileOutputStream(choice), "UTF-8"));\r
388 \r
389             Enumeration e = fr.featureColours.keys();\r
390            while(e.hasMoreElements())\r
391            {\r
392                 jalview.binding.Colour col = new jalview.binding.Colour();\r
393                 col.setName(e.nextElement().toString());\r
394                 col.setRGB(jalview.util.Format.getHexString(\r
395                         fr.getColour(col.getName())));\r
396                 ucs.addColour(col);\r
397             }\r
398 \r
399             ucs.marshal(out);\r
400             out.close();\r
401         }\r
402         catch (Exception ex)\r
403         {\r
404             ex.printStackTrace();\r
405         }\r
406     }\r
407   }\r
408 \r
409   public void invertSelection()\r
410   {\r
411     for(int i=0; i<table.getRowCount(); i++)\r
412     {\r
413       Boolean value = (Boolean)table.getValueAt(i,2);\r
414 \r
415       table.setValueAt(\r
416           new Boolean(!value.booleanValue()),\r
417                        i,2);\r
418     }\r
419   }\r
420 \r
421   public void close()\r
422   {\r
423     try\r
424     {\r
425       frame.setClosed(true);\r
426     }\r
427     catch (Exception exe)\r
428     {}\r
429 \r
430   }\r
431 \r
432   public void updateFeatureRenderer(Object [][] data)\r
433   {\r
434     fr.setFeaturePriority( data );\r
435     af.alignPanel.repaint();\r
436 \r
437     if(af.alignPanel.overviewPanel!=null)\r
438       af.alignPanel.overviewPanel.updateOverviewImage();\r
439   }\r
440 \r
441   int selectedRow =-1;\r
442   JTabbedPane tabbedPane = new JTabbedPane();\r
443   BorderLayout borderLayout1 = new BorderLayout();\r
444   BorderLayout borderLayout2 = new BorderLayout();\r
445   BorderLayout borderLayout3 = new BorderLayout();\r
446   JPanel bigPanel = new JPanel();\r
447   BorderLayout borderLayout4 = new BorderLayout();\r
448   JButton invert = new JButton();\r
449   JPanel buttonPanel = new JPanel();\r
450   JButton cancel = new JButton();\r
451   JButton ok = new JButton();\r
452   JButton loadColours = new JButton();\r
453   JButton saveColours = new JButton();\r
454   JPanel dasButtonPanel = new JPanel();\r
455   JButton fetchDAS = new JButton();\r
456   JButton saveDAS = new JButton();\r
457   private void jbInit()\r
458       throws Exception\r
459   {\r
460     this.setLayout(borderLayout1);\r
461     settingsPane.setLayout(borderLayout2);\r
462     dasSettingsPane.setLayout(borderLayout3);\r
463     bigPanel.setLayout(borderLayout4);\r
464     invert.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));\r
465     invert.setText("Invert Selection");\r
466     invert.addActionListener(new ActionListener()\r
467     {\r
468       public void actionPerformed(ActionEvent e)\r
469       {\r
470         invertSelection();\r
471       }\r
472     });\r
473     cancel.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));\r
474     cancel.setText("Cancel");\r
475     cancel.addActionListener(new ActionListener()\r
476     {\r
477       public void actionPerformed(ActionEvent e)\r
478       {\r
479           updateFeatureRenderer(originalData);\r
480           close();\r
481       }\r
482     });\r
483     ok.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));\r
484     ok.setText("OK");\r
485     ok.addActionListener(new ActionListener()\r
486     {\r
487       public void actionPerformed(ActionEvent e)\r
488       {\r
489         close();\r
490       }\r
491     });\r
492     loadColours.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));\r
493     loadColours.setText("Load Colours");\r
494     loadColours.addActionListener(new ActionListener()\r
495     {\r
496       public void actionPerformed(ActionEvent e)\r
497       {\r
498         load();\r
499       }\r
500     });\r
501     saveColours.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));\r
502     saveColours.setText("Save Colours");\r
503     saveColours.addActionListener(new ActionListener()\r
504     {\r
505       public void actionPerformed(ActionEvent e)\r
506       {\r
507         save();\r
508       }\r
509     });\r
510     transparency.addChangeListener(new ChangeListener()\r
511     {\r
512       public void stateChanged(ChangeEvent evt)\r
513       {\r
514         fr.setTransparency( (float) (100 - transparency.getValue()) / 100f);\r
515         af.alignPanel.repaint();\r
516       }\r
517     });\r
518 \r
519 \r
520     transparency.setMaximum(70);\r
521     fetchDAS.setText("Fetch DAS Features");\r
522     fetchDAS.addActionListener(new ActionListener()\r
523     {\r
524       public void actionPerformed(ActionEvent e)\r
525       {\r
526         fetchDAS_actionPerformed(e);\r
527       }\r
528     });\r
529     saveDAS.setText("Save as default");\r
530     saveDAS.addActionListener(new ActionListener()\r
531     {\r
532       public void actionPerformed(ActionEvent e)\r
533       {\r
534         saveDAS_actionPerformed(e);\r
535       }\r
536     });\r
537     dasButtonPanel.setBorder(BorderFactory.createEtchedBorder());\r
538     dasSettingsPane.setBorder(null);\r
539     this.add(tabbedPane, java.awt.BorderLayout.CENTER);\r
540     tabbedPane.addTab("Display Settings", settingsPane );\r
541     tabbedPane.addTab("DAS Settings", dasSettingsPane);\r
542     bigPanel.add(transPanel, java.awt.BorderLayout.SOUTH);\r
543     transPanel.add(transparency);\r
544     transPanel.add(invert);\r
545     buttonPanel.add(ok);\r
546     buttonPanel.add(cancel);\r
547     buttonPanel.add(loadColours);\r
548     buttonPanel.add(saveColours);\r
549     bigPanel.add(scrollPane, java.awt.BorderLayout.CENTER);\r
550     dasSettingsPane.add(dasButtonPanel, java.awt.BorderLayout.SOUTH);\r
551     dasButtonPanel.add(fetchDAS);\r
552     dasButtonPanel.add(saveDAS);\r
553     settingsPane.add(bigPanel, java.awt.BorderLayout.CENTER);\r
554     settingsPane.add(buttonPanel, java.awt.BorderLayout.SOUTH);\r
555   }\r
556 \r
557   public void fetchDAS_actionPerformed(ActionEvent e)\r
558   {\r
559     Vector selectedSources = dassourceBrowser.getSelectedSources();\r
560 \r
561     int uniprotCount = 0;\r
562     for(int i=0; i<selectedSources.size(); i++)\r
563     {\r
564      DasSource source = (DasSource)selectedSources.elementAt(i);\r
565      DasCoordinateSystem [] coords = source.getCoordinateSystem();\r
566      for(int c=0; c<coords.length; c++)\r
567      {\r
568        if (coords[c].getName().equalsIgnoreCase("UniProt"))\r
569        {\r
570          uniprotCount++;\r
571          break;\r
572        }\r
573      }\r
574     }\r
575 \r
576     System.out.println("User selection is "\r
577                        + (((float)uniprotCount/(float)selectedSources.size())*100)\r
578                        +" % Uniprot");\r
579 \r
580    new jalview.io.DasSequenceFeatureFetcher(af.getViewport().getAlignment(),\r
581                                              af,\r
582                                             selectedSources);\r
583 \r
584     af.getViewport().setShowSequenceFeatures(true);\r
585     af.showSeqFeatures.setSelected(true);\r
586   }\r
587 \r
588   public void saveDAS_actionPerformed(ActionEvent e)\r
589   {\r
590     dassourceBrowser.saveProperties(jalview.bin.Cache.applicationProperties);\r
591   }\r
592 \r
593   /////////////////////////////////////////////////////////////////////////\r
594   // http://java.sun.com/docs/books/tutorial/uiswing/components/table.html\r
595   /////////////////////////////////////////////////////////////////////////\r
596   class FeatureTableModel\r
597       extends AbstractTableModel\r
598   {\r
599     FeatureTableModel(Object[][] data)\r
600     {\r
601       this.data = data;\r
602     }\r
603 \r
604     private String[] columnNames = {"Feature Type", "Colour","Display"};\r
605           private Object[][] data;\r
606 \r
607           public Object[][] getData()\r
608           {\r
609             return data;\r
610           }\r
611 \r
612           public void setData(Object[][] data)\r
613           {\r
614             this.data = data;\r
615           }\r
616 \r
617           public int getColumnCount() {\r
618               return columnNames.length;\r
619           }\r
620 \r
621           public Object[] getRow(int row)\r
622           {\r
623             return data[row];\r
624           }\r
625 \r
626           public int getRowCount() {\r
627               return data.length;\r
628           }\r
629 \r
630           public String getColumnName(int col) {\r
631               return columnNames[col];\r
632           }\r
633 \r
634           public Object getValueAt(int row, int col) {\r
635               return data[row][col];\r
636           }\r
637 \r
638           public Class getColumnClass(int c) {\r
639               return getValueAt(0, c).getClass();\r
640           }\r
641 \r
642           public boolean isCellEditable(int row, int col) {\r
643               return col==0 ? false:true;\r
644           }\r
645 \r
646           public void setValueAt(Object value, int row, int col) {\r
647               data[row][col] = value;\r
648               fireTableCellUpdated(row, col);\r
649               updateFeatureRenderer(data);\r
650           }\r
651 \r
652     }\r
653     class ColorRenderer extends JLabel\r
654                               implements TableCellRenderer {\r
655        javax.swing.border.Border unselectedBorder = null;\r
656        javax.swing.border.Border selectedBorder = null;\r
657 \r
658        public ColorRenderer() {\r
659            setOpaque(true); //MUST do this for background to show up.\r
660        }\r
661 \r
662        public Component getTableCellRendererComponent(\r
663                                JTable table, Object color,\r
664                                boolean isSelected, boolean hasFocus,\r
665                                int row, int column) {\r
666            Color newColor = (Color)color;\r
667            setBackground(newColor);\r
668                if (isSelected) {\r
669                    if (selectedBorder == null) {\r
670                        selectedBorder = BorderFactory.createMatteBorder(2,5,2,5,\r
671                                                  table.getSelectionBackground());\r
672                    }\r
673                    setBorder(selectedBorder);\r
674                } else {\r
675                    if (unselectedBorder == null) {\r
676                        unselectedBorder = BorderFactory.createMatteBorder(2,5,2,5,\r
677                                                  table.getBackground());\r
678                    }\r
679                    setBorder(unselectedBorder);\r
680                }\r
681 \r
682            setToolTipText("RGB value: " + newColor.getRed() + ", "\r
683                                         + newColor.getGreen() + ", "\r
684                                         + newColor.getBlue());\r
685            return this;\r
686        }\r
687    }\r
688 }\r
689 \r
690  class ColorEditor extends AbstractCellEditor\r
691                           implements TableCellEditor,\r
692                                      ActionListener {\r
693      Color currentColor;\r
694      JButton button;\r
695      JColorChooser colorChooser;\r
696      JDialog dialog;\r
697      protected static final String EDIT = "edit";\r
698 \r
699      public ColorEditor() {\r
700          //Set up the editor (from the table's point of view),\r
701          //which is a button.\r
702          //This button brings up the color chooser dialog,\r
703          //which is the editor from the user's point of view.\r
704          button = new JButton();\r
705          button.setActionCommand(EDIT);\r
706          button.addActionListener(this);\r
707          button.setBorderPainted(false);\r
708          //Set up the dialog that the button brings up.\r
709          colorChooser = new JColorChooser();\r
710          dialog = JColorChooser.createDialog(button,\r
711                                          "Select new Colour",\r
712                                          true,  //modal\r
713                                          colorChooser,\r
714                                          this,  //OK button handler\r
715                                          null); //no CANCEL button handler\r
716      }\r
717 \r
718      /**\r
719       * Handles events from the editor button and from\r
720       * the dialog's OK button.\r
721       */\r
722      public void actionPerformed(ActionEvent e) {\r
723 \r
724           if (EDIT.equals(e.getActionCommand())) {\r
725              //The user has clicked the cell, so\r
726              //bring up the dialog.\r
727              button.setBackground(currentColor);\r
728              colorChooser.setColor(currentColor);\r
729              dialog.setVisible(true);\r
730 \r
731              //Make the renderer reappear.\r
732              fireEditingStopped();\r
733 \r
734          } else { //User pressed dialog's "OK" button.\r
735              currentColor = colorChooser.getColor();\r
736          }\r
737      }\r
738 \r
739      //Implement the one CellEditor method that AbstractCellEditor doesn't.\r
740      public Object getCellEditorValue() {\r
741          return currentColor;\r
742      }\r
743 \r
744      //Implement the one method defined by TableCellEditor.\r
745      public Component getTableCellEditorComponent(JTable table,\r
746                                                   Object value,\r
747                                                   boolean isSelected,\r
748                                                   int row,\r
749                                                   int column) {\r
750          currentColor = (Color)value;\r
751          return button;\r
752      }\r
753 }\r