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