Null pointer if user presses shift before anything else
[jalview.git] / src / jalview / gui / UserDefinedColours.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 \r
23 import jalview.io.*;\r
24 \r
25 import jalview.jbgui.*;\r
26 \r
27 import jalview.schemes.*;\r
28 \r
29 import java.awt.*;\r
30 import java.awt.event.*;\r
31 \r
32 import java.io.*;\r
33 \r
34 import java.util.*;\r
35 \r
36 import javax.swing.*;\r
37 import javax.swing.event.*;\r
38 \r
39 \r
40 \r
41 /**\r
42  * DOCUMENT ME!\r
43  *\r
44  * @author $author$\r
45  * @version $Revision$\r
46  */\r
47 public class UserDefinedColours extends GUserDefinedColours\r
48     implements ChangeListener\r
49 {\r
50     AlignmentPanel ap;\r
51     SequenceGroup seqGroup;\r
52     Vector selectedButtons;\r
53     ColourSchemeI oldColourScheme;\r
54     JInternalFrame frame;\r
55 \r
56     /**\r
57      * Creates a new UserDefinedColours object.\r
58      *\r
59      * @param ap DOCUMENT ME!\r
60      * @param sg DOCUMENT ME!\r
61      */\r
62     public UserDefinedColours(AlignmentPanel ap, SequenceGroup sg)\r
63     {\r
64         super();\r
65         frame = new JInternalFrame();\r
66         frame.setContentPane(this);\r
67         Desktop.addInternalFrame(frame, "User Defined Colours", 720, 370, true);\r
68 \r
69         if (System.getProperty("os.name").startsWith("Mac"))\r
70         {\r
71             frame.setSize(760, 370);\r
72         }\r
73 \r
74         if (sg != null)\r
75         {\r
76             frame.setTitle(frame.getTitle() + " (" + sg.getName() + ")");\r
77         }\r
78 \r
79         colorChooser.getSelectionModel().addChangeListener(this);\r
80 \r
81         this.ap = ap;\r
82         seqGroup = sg;\r
83 \r
84         if (seqGroup != null)\r
85         {\r
86             oldColourScheme = seqGroup.cs;\r
87         }\r
88         else\r
89         {\r
90             oldColourScheme = ap.av.getGlobalColourScheme();\r
91         }\r
92 \r
93         if (oldColourScheme instanceof UserColourScheme)\r
94         {\r
95               schemeName.setText( ( (UserColourScheme) oldColourScheme).getName());\r
96         }\r
97         for (int i = 0; i < 20; i++)\r
98         {\r
99             makeButton(ResidueProperties.aa2Triplet.get(ResidueProperties.aa[i]) +\r
100                 "", ResidueProperties.aa[i]);\r
101         }\r
102 \r
103         makeButton("B", "B");\r
104         makeButton("Z", "Z");\r
105         makeButton("X", "X");\r
106         makeButton("Gap", "-");\r
107     }\r
108 \r
109     /**\r
110      * DOCUMENT ME!\r
111      *\r
112      * @param evt DOCUMENT ME!\r
113      */\r
114     public void stateChanged(ChangeEvent evt)\r
115     {\r
116         if (selectedButtons != null)\r
117         {\r
118           JButton button;\r
119           for(int i=0; i<selectedButtons.size(); i++)\r
120           {\r
121             button = (JButton)selectedButtons.elementAt(i);\r
122             button.setBackground(colorChooser.getColor());\r
123             button.setForeground( button.getBackground().brighter().brighter().brighter());\r
124           }\r
125         }\r
126     }\r
127 \r
128     /**\r
129      * DOCUMENT ME!\r
130      *\r
131      * @param e DOCUMENT ME!\r
132      */\r
133     public void colourButtonPressed(MouseEvent e)\r
134     {\r
135       if(selectedButtons == null)\r
136         selectedButtons = new Vector();\r
137 \r
138       JButton pressed = (JButton) e.getSource();\r
139 \r
140       if(e.isShiftDown())\r
141       {\r
142         JButton start, end = (JButton) e.getSource();\r
143         if(selectedButtons.size()>1)\r
144           start = (JButton)selectedButtons.elementAt(selectedButtons.size()-1);\r
145         else\r
146           start = (JButton) e.getSource();\r
147 \r
148         int startIndex=0, endIndex=0;\r
149         for(int b=0; b<buttonPanel.getComponentCount(); b++)\r
150         {\r
151           if(buttonPanel.getComponent(b)==start)\r
152             startIndex = b;\r
153           if(buttonPanel.getComponent(b)==end)\r
154             endIndex = b;\r
155         }\r
156 \r
157         if(startIndex > endIndex)\r
158         {\r
159           int temp = startIndex;\r
160           startIndex = endIndex;\r
161           endIndex = temp;\r
162         }\r
163 \r
164         for(int b=startIndex; b<=endIndex; b++)\r
165         {\r
166           JButton button = (JButton)buttonPanel.getComponent(b);\r
167           if(!selectedButtons.contains(button))\r
168           {\r
169             button.setForeground(button.getBackground().brighter().brighter());\r
170             selectedButtons.add(button);\r
171           }\r
172         }\r
173       }\r
174       else if(!e.isControlDown())\r
175       {\r
176         for(int b=0; b<selectedButtons.size(); b++)\r
177         {\r
178           JButton button = (JButton)selectedButtons.elementAt(b);\r
179           button.setForeground(button.getBackground().darker().darker());\r
180         }\r
181         selectedButtons.clear();\r
182         pressed.setForeground( pressed.getBackground().brighter().brighter());\r
183         selectedButtons.addElement(pressed);\r
184 \r
185       }\r
186       else if(e.isControlDown())\r
187       {\r
188         if(selectedButtons.contains(pressed))\r
189         {\r
190           pressed.setForeground(pressed.getBackground().darker().darker());\r
191           selectedButtons.remove(pressed);\r
192         }\r
193         else\r
194         {\r
195           pressed.setForeground( pressed.getBackground().brighter().brighter());\r
196           selectedButtons.addElement(pressed);\r
197         }\r
198       }\r
199 \r
200       if(selectedButtons.size()>0)\r
201       colorChooser.setColor( ((JButton)selectedButtons.elementAt(0)).getBackground());\r
202     }\r
203 \r
204     /**\r
205      * DOCUMENT ME!\r
206      *\r
207      * @param label DOCUMENT ME!\r
208      * @param aa DOCUMENT ME!\r
209      */\r
210     void makeButton(String label, String aa)\r
211     {\r
212         final JButton button = new JButton();\r
213         Color col = Color.white;\r
214 \r
215         try\r
216         {\r
217             col = oldColourScheme.findColour(aa, -1);\r
218         }\r
219         catch (Exception ex)\r
220         {\r
221         //  ex.printStackTrace();\r
222         }\r
223 \r
224         button.setBackground(col);\r
225         button.setText(label);\r
226         button.setForeground(col.darker().darker().darker());\r
227         button.setFont(new java.awt.Font("Verdana", 1, 10));\r
228         button.addMouseListener(new java.awt.event.MouseAdapter()\r
229             {\r
230                 public void mouseClicked(MouseEvent e)\r
231                 {\r
232                     colourButtonPressed(e);\r
233                 }\r
234             });\r
235 \r
236         buttonPanel.add(button, null);\r
237     }\r
238 \r
239     /**\r
240      * DOCUMENT ME!\r
241      *\r
242      * @param e DOCUMENT ME!\r
243      */\r
244     protected void okButton_actionPerformed(ActionEvent e)\r
245     {\r
246         applyButton_actionPerformed(null);\r
247 \r
248         try\r
249         {\r
250             frame.setClosed(true);\r
251         }\r
252         catch (Exception ex)\r
253         {\r
254         }\r
255     }\r
256 \r
257     /**\r
258      * DOCUMENT ME!\r
259      *\r
260      * @param e DOCUMENT ME!\r
261      */\r
262     protected void applyButton_actionPerformed(ActionEvent e)\r
263     {\r
264         UserColourScheme ucs = getSchemeFromGUI();\r
265         ucs.setName(schemeName.getText());\r
266 \r
267         if (seqGroup != null)\r
268         {\r
269             seqGroup.cs = ucs;\r
270             ap.repaint();\r
271         }\r
272         else\r
273         {\r
274             ap.alignFrame.changeColour(ucs);\r
275         }\r
276     }\r
277 \r
278     UserColourScheme getSchemeFromGUI()\r
279     {\r
280       Color[] newColours = new Color[24];\r
281 \r
282       for (int i = 0; i < 24; i++)\r
283       {\r
284         JButton button = (JButton) buttonPanel.getComponent(i);\r
285         newColours[i] = button.getBackground();\r
286       }\r
287 \r
288       UserColourScheme ucs = new UserColourScheme(newColours);\r
289       ucs.setThreshold(0, ap.av.getIgnoreGapsConsensus());\r
290 \r
291       return ucs;\r
292     }\r
293 \r
294 \r
295 \r
296     /**\r
297      * DOCUMENT ME!\r
298      *\r
299      * @param e DOCUMENT ME!\r
300      */\r
301     protected void loadbutton_actionPerformed(ActionEvent e)\r
302     {\r
303         JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.getProperty(\r
304                     "LAST_DIRECTORY"), new String[] { "jc" },\r
305                 new String[] { "Jalview User Colours" }, "Jalview User Colours");\r
306         chooser.setFileView(new jalview.io.JalviewFileView());\r
307         chooser.setDialogTitle("Load colour scheme");\r
308         chooser.setToolTipText("Load");\r
309 \r
310         int value = chooser.showOpenDialog(this);\r
311 \r
312         if (value == JalviewFileChooser.APPROVE_OPTION)\r
313         {\r
314             File choice = chooser.getSelectedFile();\r
315             jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice.getParent());\r
316             String defaultColours = jalview.bin.Cache.getDefault("USER_DEFINED_COLOURS",\r
317                 choice.getPath());\r
318             if (defaultColours.indexOf(choice.getPath()) == -1)\r
319               defaultColours = defaultColours.concat("|").concat(choice.getPath());\r
320 \r
321             jalview.bin.Cache.setProperty("USER_DEFINED_COLOURS", defaultColours);\r
322 \r
323 \r
324             UserColourScheme ucs = loadColours(choice.getAbsolutePath());\r
325             Color[] colors = ucs.getColours();\r
326             schemeName.setText(ucs.getName());\r
327 \r
328             for (int i = 0; i < colors.length; i++)\r
329             {\r
330                 JButton button = (JButton) buttonPanel.getComponent(i);\r
331                 button.setBackground(colors[i]);\r
332             }\r
333         }\r
334     }\r
335 \r
336     /**\r
337      * DOCUMENT ME!\r
338      *\r
339      * @return DOCUMENT ME!\r
340      */\r
341     public static UserColourScheme loadDefaultColours()\r
342     {\r
343         UserColourScheme ret = null;\r
344 \r
345         String colours = jalview.bin.Cache.getProperty("USER_DEFINED_COLOURS");\r
346         if ( colours != null )\r
347         {\r
348           if(colours.indexOf("|")>-1)\r
349             colours = colours.substring(0, colours.indexOf("|"));\r
350 \r
351           ret = loadColours(colours);\r
352         }\r
353 \r
354         if(ret == null)\r
355         {\r
356           Color[] newColours = new Color[24];\r
357           for (int i = 0; i < 24; i++)\r
358           {\r
359             newColours[i] = Color.white;\r
360           }\r
361           ret =  new UserColourScheme(newColours);\r
362         }\r
363 \r
364         return ret;\r
365     }\r
366 \r
367     /**\r
368      * DOCUMENT ME!\r
369      *\r
370      * @param file DOCUMENT ME!\r
371      *\r
372      * @return DOCUMENT ME!\r
373      */\r
374     static UserColourScheme loadColours(String file)\r
375     {\r
376          UserColourScheme ucs = null;\r
377          Color[]  newColours = null;\r
378 \r
379         try\r
380         {\r
381             InputStreamReader in = new InputStreamReader(new FileInputStream(\r
382                         file), "UTF-8");\r
383 \r
384             jalview.binding.JalviewUserColours jucs = new jalview.binding.JalviewUserColours();\r
385             jucs = (jalview.binding.JalviewUserColours) jucs.unmarshal(in);\r
386 \r
387             newColours = new Color[jucs.getColourCount()];\r
388 \r
389             for (int i = 0; i < 24; i++)\r
390             {\r
391               newColours[i] = new Color(Integer.parseInt(\r
392                   jucs.getColour(i).getRGB(), 16));\r
393             }\r
394             if (newColours != null)\r
395             {\r
396               ucs = new UserColourScheme(newColours);\r
397               ucs.setName( jucs.getSchemeName() );\r
398             }\r
399 \r
400         }\r
401         catch (Exception ex)\r
402         {\r
403             System.out.println("Error loading User ColourFile\n"+ex);\r
404         }\r
405 \r
406 \r
407        return ucs;\r
408     }\r
409 \r
410     /**\r
411      * DOCUMENT ME!\r
412      *\r
413      * @param e DOCUMENT ME!\r
414      */\r
415     protected void savebutton_actionPerformed(ActionEvent e)\r
416     {\r
417       if(schemeName.getText().trim().length()<1)\r
418       {\r
419         JOptionPane.showInternalMessageDialog(Desktop.desktop,\r
420                                               "User colour scheme must have a name!",\r
421                                               "No name for colour scheme",\r
422                                               JOptionPane.WARNING_MESSAGE);\r
423         return;\r
424       }\r
425 \r
426       if(userColourSchemes!=null && userColourSchemes.containsKey(schemeName.getText()) )\r
427       {\r
428         int reply = JOptionPane.showInternalConfirmDialog(Desktop.desktop, "Colour scheme "+schemeName.getText()+ " exists."\r
429             +"\nContinue saving colour scheme as "+schemeName.getText()+"?",\r
430            "Duplicate scheme name", JOptionPane.YES_NO_OPTION);\r
431         if(reply != JOptionPane.YES_OPTION)\r
432           return;\r
433 \r
434          userColourSchemes.remove(schemeName.getText());\r
435       }\r
436         JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.getProperty(\r
437                     "LAST_DIRECTORY"), new String[] { "jc" },\r
438                 new String[] { "Jalview User Colours" }, "Jalview User Colours");\r
439 \r
440         chooser.setFileView(new jalview.io.JalviewFileView());\r
441         chooser.setDialogTitle("Save colour scheme");\r
442         chooser.setToolTipText("Save");\r
443 \r
444         int value = chooser.showSaveDialog(this);\r
445 \r
446         if (value == JalviewFileChooser.APPROVE_OPTION)\r
447         {\r
448             String choice = chooser.getSelectedFile().getPath();\r
449             String defaultColours = jalview.bin.Cache.getDefault("USER_DEFINED_COLOURS", choice);\r
450             if(defaultColours.indexOf(choice)==-1)\r
451             {\r
452               if(defaultColours.length()>0)\r
453                 defaultColours = defaultColours.concat("|");\r
454               defaultColours = defaultColours.concat(choice);\r
455             }\r
456 \r
457             userColourSchemes.put(schemeName.getText(), getSchemeFromGUI());\r
458 \r
459             ap.alignFrame.updateUserColourMenu();\r
460 \r
461             jalview.bin.Cache.setProperty("USER_DEFINED_COLOURS", defaultColours);\r
462 \r
463             jalview.binding.JalviewUserColours ucs = new jalview.binding.JalviewUserColours();\r
464             ucs.setSchemeName(schemeName.getText());\r
465             try\r
466             {\r
467                 PrintWriter out = new PrintWriter(new OutputStreamWriter(\r
468                             new FileOutputStream(choice), "UTF-8"));\r
469 \r
470                 for (int i = 0; i < 24; i++)\r
471                 {\r
472                     JButton button = (JButton) buttonPanel.getComponent(i);\r
473                     jalview.binding.Colour col = new jalview.binding.Colour();\r
474                     col.setName(button.getText());\r
475                     col.setRGB(jalview.util.Format.getHexString(\r
476                             button.getBackground()));\r
477                     ucs.addColour(col);\r
478                 }\r
479 \r
480                 ucs.marshal(out);\r
481                 out.close();\r
482             }\r
483             catch (Exception ex)\r
484             {\r
485                 ex.printStackTrace();\r
486             }\r
487         }\r
488     }\r
489 \r
490     /**\r
491      * DOCUMENT ME!\r
492      *\r
493      * @param e DOCUMENT ME!\r
494      */\r
495     protected void cancelButton_actionPerformed(ActionEvent e)\r
496     {\r
497         if (seqGroup != null)\r
498         {\r
499             seqGroup.cs = oldColourScheme;\r
500         }\r
501         else\r
502         {\r
503             ap.av.setGlobalColourScheme(oldColourScheme);\r
504         }\r
505 \r
506         ap.repaint();\r
507 \r
508         try\r
509         {\r
510             frame.setClosed(true);\r
511         }\r
512         catch (Exception ex)\r
513         {\r
514         }\r
515     }\r
516 \r
517 \r
518     static Hashtable userColourSchemes;\r
519 \r
520     public static Hashtable getUserColourSchemes()\r
521     {\r
522       return userColourSchemes;\r
523     }\r
524 \r
525     public static void initUserColourSchemes(String files)\r
526     {\r
527       userColourSchemes = new Hashtable();\r
528 \r
529       if(files==null || files.length()==0)\r
530         return;\r
531 \r
532 \r
533       // In case colours can't be loaded, we'll remove them\r
534       // from the default list here.\r
535       StringBuffer coloursFound = new StringBuffer();\r
536       StringTokenizer st = new StringTokenizer(files, "|");\r
537       while (st.hasMoreElements())\r
538       {\r
539         String file = st.nextToken();\r
540         try\r
541         {\r
542           UserColourScheme ucs = loadColours(file);\r
543           if (ucs != null)\r
544           {\r
545             if (coloursFound.length() > 0)\r
546               coloursFound.append("|");\r
547             coloursFound.append(file);\r
548             userColourSchemes.put(ucs.getName(), ucs);\r
549           }\r
550         }\r
551         catch (Exception ex)\r
552         {\r
553           System.out.println("Error loading User ColourFile\n" + ex);\r
554         }\r
555       }\r
556       if (!files.equals(coloursFound.toString()))\r
557       {\r
558         if (coloursFound.toString().length() > 1)\r
559           jalview.bin.Cache.setProperty("USER_DEFINED_COLOURS",\r
560                                         coloursFound.toString());\r
561         else\r
562           jalview.bin.Cache.applicationProperties.remove("USER_DEFINED_COLOURS");\r
563       }\r
564     }\r
565 \r
566     public static void removeColourFromDefaults(String target)\r
567     {\r
568       // The only way to find colours by name is to load them in\r
569       // In case colours can't be loaded, we'll remove them\r
570       // from the default list here.\r
571 \r
572       userColourSchemes = new Hashtable();\r
573 \r
574       StringBuffer coloursFound = new StringBuffer();\r
575       StringTokenizer st = new StringTokenizer(\r
576            jalview.bin.Cache.getProperty("USER_DEFINED_COLOURS"), "|");\r
577 \r
578       while (st.hasMoreElements())\r
579       {\r
580         String file = st.nextToken();\r
581         try\r
582         {\r
583           UserColourScheme ucs = loadColours(file);\r
584           if (ucs != null && !ucs.getName().equals(target))\r
585           {\r
586             if (coloursFound.length() > 0)\r
587               coloursFound.append("|");\r
588             coloursFound.append(file);\r
589             userColourSchemes.put(ucs.getName(), ucs);\r
590           }\r
591         }\r
592         catch (Exception ex)\r
593         {\r
594           System.out.println("Error loading User ColourFile\n" + ex);\r
595         }\r
596       }\r
597 \r
598       if (coloursFound.toString().length() > 1)\r
599         jalview.bin.Cache.setProperty("USER_DEFINED_COLOURS", coloursFound.toString());\r
600       else\r
601         jalview.bin.Cache.applicationProperties.remove("USER_DEFINED_COLOURS");\r
602 \r
603     }\r
604 }\r