JAL-4409 JAL-4160 Don't let getdown turn jalviewX:// URIs into absolute local file...
[jalview.git] / src / jalview / gui / CutAndPasteTransfer.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.gui;
22
23 import java.awt.Toolkit;
24 import java.awt.datatransfer.Clipboard;
25 import java.awt.datatransfer.DataFlavor;
26 import java.awt.datatransfer.StringSelection;
27 import java.awt.datatransfer.Transferable;
28 import java.awt.event.ActionEvent;
29 import java.awt.event.ActionListener;
30 import java.awt.event.MouseEvent;
31 import java.io.FileNotFoundException;
32 import java.io.FileWriter;
33 import java.io.IOException;
34 import java.io.PrintWriter;
35
36 import javax.swing.JMenuItem;
37 import javax.swing.JPopupMenu;
38 import javax.swing.SwingUtilities;
39
40 import jalview.api.AlignViewportI;
41 import jalview.api.AlignmentViewPanel;
42 import jalview.api.ComplexAlignFile;
43 import jalview.api.FeatureSettingsModelI;
44 import jalview.api.FeaturesDisplayedI;
45 import jalview.api.FeaturesSourceI;
46 import jalview.bin.Cache;
47 import jalview.bin.Jalview;
48 import jalview.datamodel.AlignmentI;
49 import jalview.datamodel.HiddenColumns;
50 import jalview.datamodel.SequenceI;
51 import jalview.io.AlignmentFileReaderI;
52 import jalview.io.AppletFormatAdapter;
53 import jalview.io.DataSourceType;
54 import jalview.io.FileFormatException;
55 import jalview.io.FileFormatI;
56 import jalview.io.FormatAdapter;
57 import jalview.io.IdentifyFile;
58 import jalview.io.JalviewFileChooser;
59 import jalview.io.JalviewFileView;
60 import jalview.jbgui.GCutAndPasteTransfer;
61 import jalview.json.binding.biojson.v1.ColourSchemeMapper;
62 import jalview.schemes.ColourSchemeI;
63 import jalview.util.MessageManager;
64
65 /**
66  * Cut'n'paste files into the desktop See JAL-1105
67  * 
68  * @author $author$
69  * @version $Revision$
70  */
71 public class CutAndPasteTransfer extends GCutAndPasteTransfer
72 {
73
74   AlignmentViewPanel alignpanel;
75
76   AlignViewportI viewport;
77
78   AlignmentFileReaderI source = null;
79
80   public CutAndPasteTransfer()
81   {
82     this.setFrameIcon(null);
83     SwingUtilities.invokeLater(new Runnable()
84     {
85       @Override
86       public void run()
87       {
88         textarea.requestFocus();
89       }
90     });
91
92   }
93
94   /**
95    * DOCUMENT ME!
96    */
97   public void setForInput(AlignmentViewPanel viewpanel)
98   {
99     this.alignpanel = viewpanel;
100     if (alignpanel != null)
101     {
102       this.viewport = alignpanel.getAlignViewport();
103     }
104     if (viewport != null)
105     {
106       ok.setText(MessageManager.getString("action.add"));
107     }
108
109     getContentPane().add(inputButtonPanel, java.awt.BorderLayout.SOUTH);
110   }
111
112   /**
113    * DOCUMENT ME!
114    * 
115    * @return DOCUMENT ME!
116    */
117   public String getText()
118   {
119     return textarea.getText();
120   }
121
122   /**
123    * DOCUMENT ME!
124    * 
125    * @param text
126    *          DOCUMENT ME!
127    */
128   public void setText(String text)
129   {
130     textarea.setText(text);
131   }
132
133   public void appendText(String text)
134   {
135     textarea.append(text);
136   }
137
138   @Override
139   public void save_actionPerformed(ActionEvent e)
140   {
141     // TODO: JAL-3048 JalviewFileChooser - Save option
142
143     JalviewFileChooser chooser = new JalviewFileChooser(
144             Cache.getProperty("LAST_DIRECTORY"));
145
146     chooser.setAcceptAllFileFilterUsed(false);
147     chooser.setFileView(new JalviewFileView());
148     chooser.setDialogTitle(
149             MessageManager.getString("label.save_text_to_file"));
150     chooser.setToolTipText(MessageManager.getString("action.save"));
151
152     int value = chooser.showSaveDialog(this);
153
154     if (value == JalviewFileChooser.APPROVE_OPTION)
155     {
156       try
157       {
158         PrintWriter out = new PrintWriter(
159                 new FileWriter(chooser.getSelectedFile()));
160
161         out.print(getText());
162         out.close();
163       } catch (Exception ex)
164       {
165         ex.printStackTrace();
166       }
167
168     }
169   }
170
171   /**
172    * DOCUMENT ME!
173    * 
174    * @param e
175    *          DOCUMENT ME!
176    */
177   @Override
178   public void copyItem_actionPerformed(ActionEvent e)
179   {
180     textarea.getSelectedText();
181     Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
182     c.setContents(new StringSelection(textarea.getSelectedText()), null);
183   }
184
185   /**
186    * DOCUMENT ME!
187    * 
188    * @param e
189    *          DOCUMENT ME!
190    */
191   @Override
192   public void pasteMenu_actionPerformed(ActionEvent e)
193   {
194     Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
195     Transferable contents = c.getContents(this);
196
197     if (contents == null)
198     {
199       return;
200     }
201
202     try
203     {
204       textarea.append(
205               (String) contents.getTransferData(DataFlavor.stringFlavor));
206     } catch (Exception ex)
207     {
208     }
209   }
210
211   /**
212    * DOCUMENT ME!
213    * 
214    * @param e
215    *          DOCUMENT ME!
216    */
217   @Override
218   public void ok_actionPerformed(ActionEvent e)
219   {
220     String text = getText();
221     if (text.trim().length() < 1)
222     {
223       return;
224     }
225
226     FileFormatI format = null;
227     try
228     {
229       format = new IdentifyFile().identify(text, DataSourceType.PASTE);
230     } catch (FileNotFoundException e0)
231     {
232       // this won't happen
233     } catch (FileFormatException e1)
234     {
235       // leave as null
236     }
237     if (format == null)
238     {
239       System.err
240               .println(MessageManager.getString("label.couldnt_read_data"));
241       if (!Jalview.isHeadlessMode())
242       {
243         JvOptionPane.showInternalMessageDialog(Desktop.desktop,
244                 AppletFormatAdapter.getSupportedFormats(),
245                 MessageManager.getString("label.couldnt_read_data"),
246                 JvOptionPane.WARNING_MESSAGE);
247       }
248       return;
249     }
250
251     // TODO: identify feature, annotation or tree file and parse appropriately.
252     AlignmentI al = null;
253
254     try
255     {
256       FormatAdapter fa = new FormatAdapter(alignpanel);
257       al = fa.readFile(getText(), DataSourceType.PASTE, format);
258       source = fa.getAlignFile();
259
260     } catch (IOException ex)
261     {
262       JvOptionPane.showInternalMessageDialog(Desktop.desktop, MessageManager
263               .formatMessage("label.couldnt_read_pasted_text", new String[]
264               { ex.toString() }),
265               MessageManager.getString("label.error_parsing_text"),
266               JvOptionPane.WARNING_MESSAGE);
267     }
268
269     if (al != null && al.hasValidSequence())
270     {
271       String title = MessageManager
272               .formatMessage("label.input_cut_paste_params", new String[]
273               { format.getName() });
274       FeatureSettingsModelI proxyColourScheme = source
275               .getFeatureColourScheme();
276
277       /*
278        * if the view panel was closed its alignment is nulled
279        * and this is an orphaned cut and paste window
280        */
281       if (viewport != null && viewport.getAlignment() != null)
282       {
283         ((AlignViewport) viewport).addAlignment(al, title);
284         viewport.applyFeaturesStyle(proxyColourScheme);
285       }
286       else
287       {
288
289         AlignFrame af;
290         if (source instanceof ComplexAlignFile)
291         {
292           HiddenColumns hidden = ((ComplexAlignFile) source)
293                   .getHiddenColumns();
294           SequenceI[] hiddenSeqs = ((ComplexAlignFile) source)
295                   .getHiddenSequences();
296           boolean showSeqFeatures = ((ComplexAlignFile) source)
297                   .isShowSeqFeatures();
298           String colourSchemeName = ((ComplexAlignFile) source)
299                   .getGlobalColourScheme();
300           FeaturesDisplayedI fd = ((ComplexAlignFile) source)
301                   .getDisplayedFeatures();
302           af = new AlignFrame(al, hiddenSeqs, hidden,
303                   AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
304           af.getViewport().setShowSequenceFeatures(showSeqFeatures);
305           af.getViewport().setFeaturesDisplayed(fd);
306           af.setMenusForViewport();
307           ColourSchemeI cs = ColourSchemeMapper
308                   .getJalviewColourScheme(colourSchemeName, al);
309           if (cs != null)
310           {
311             af.changeColour(cs);
312           }
313         }
314         else
315         {
316           af = new AlignFrame(al, AlignFrame.DEFAULT_WIDTH,
317                   AlignFrame.DEFAULT_HEIGHT);
318           if (source instanceof FeaturesSourceI)
319           {
320             af.getViewport().setShowSequenceFeatures(true);
321           }
322         }
323         if (proxyColourScheme != null)
324         {
325           af.getViewport().applyFeaturesStyle(proxyColourScheme);
326         }
327         af.currentFileFormat = format;
328         Desktop.addInternalFrame(af, title, AlignFrame.DEFAULT_WIDTH,
329                 AlignFrame.DEFAULT_HEIGHT);
330         af.setStatus(MessageManager
331                 .getString("label.successfully_pasted_alignment_file"));
332
333         try
334         {
335           af.setMaximum(Cache.getDefault("SHOW_FULLSCREEN", false));
336         } catch (Exception ex)
337         {
338         }
339       }
340     }
341     else
342     {
343       System.err
344               .println(MessageManager.getString("label.couldnt_read_data"));
345       if (!Jalview.isHeadlessMode())
346       {
347         JvOptionPane.showInternalMessageDialog(Desktop.desktop,
348                 AppletFormatAdapter.getSupportedFormats(),
349                 MessageManager.getString("label.couldnt_read_data"),
350                 JvOptionPane.WARNING_MESSAGE);
351       }
352     }
353   }
354
355   /**
356    * DOCUMENT ME!
357    * 
358    * @param e
359    *          DOCUMENT ME!
360    */
361   @Override
362   public void cancel_actionPerformed(ActionEvent e)
363   {
364     try
365     {
366       this.setClosed(true);
367     } catch (Exception ex)
368     {
369     }
370   }
371
372   @Override
373   public void textarea_mousePressed(MouseEvent e)
374   {
375     /*
376      * isPopupTrigger is checked in mousePressed on Mac,
377      * in mouseReleased on Windows
378      */
379     if (e.isPopupTrigger())
380     {
381       JPopupMenu popup = new JPopupMenu(
382               MessageManager.getString("action.edit"));
383       JMenuItem item = new JMenuItem(
384               MessageManager.getString("action.copy"));
385       item.addActionListener(new ActionListener()
386       {
387         @Override
388         public void actionPerformed(ActionEvent e)
389         {
390           copyItem_actionPerformed(e);
391         }
392       });
393       popup.add(item);
394       item = new JMenuItem(MessageManager.getString("action.paste"));
395       item.addActionListener(new ActionListener()
396       {
397         @Override
398         public void actionPerformed(ActionEvent e)
399         {
400           pasteMenu_actionPerformed(e);
401         }
402       });
403       popup.add(item);
404       popup.show(this, e.getX() + 10, e.getY() + textarea.getY() + 40);
405
406     }
407   }
408
409 }