PageRenderTime 43ms CodeModel.GetById 20ms app.highlight 20ms RepoModel.GetById 0ms app.codeStats 0ms

/jEdit/tags/jedit-4-3-pre5/org/gjt/sp/jedit/textarea/TextAreaTransferHandler.java

#
Java | 438 lines | 323 code | 55 blank | 60 comment | 54 complexity | aeb04be21c7a0d80364b2e64bfe33c4b MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0, Apache-2.0, LGPL-2.0, LGPL-3.0, GPL-2.0, CC-BY-SA-3.0, LGPL-2.1, GPL-3.0, MPL-2.0-no-copyleft-exception, IPL-1.0
  1/*
  2 * TextAreaTransferHandler.java - Drag and drop support
  3 * :tabSize=8:indentSize=8:noTabs=false:
  4 * :folding=explicit:collapseFolds=1:
  5 *
  6 * Copyright (C) 2004 Slava Pestov
  7 *
  8 * This program is free software; you can redistribute it and/or
  9 * modify it under the terms of the GNU General Public License
 10 * as published by the Free Software Foundation; either version 2
 11 * of the License, or any later version.
 12 *
 13 * This program is distributed in the hope that it will be useful,
 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 16 * GNU General Public License for more details.
 17 *
 18 * You should have received a copy of the GNU General Public License
 19 * along with this program; if not, write to the Free Software
 20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 21 */
 22
 23package org.gjt.sp.jedit.textarea;
 24
 25//{{{ Imports
 26import javax.swing.*;
 27import java.awt.datatransfer.*;
 28import java.io.File;
 29import java.util.Iterator;
 30import java.util.List;
 31import java.net.URI;
 32import org.gjt.sp.jedit.Buffer;
 33import org.gjt.sp.jedit.EditPane;
 34import org.gjt.sp.jedit.GUIUtilities;
 35import org.gjt.sp.jedit.jEdit;
 36import org.gjt.sp.util.Log;
 37//}}}
 38
 39class TextAreaTransferHandler extends TransferHandler
 40{
 41	/* I assume that there can be only one drag operation at the time */
 42	private static JEditTextArea dragSource;
 43	private static boolean compoundEdit;
 44	private static boolean sameTextArea;
 45	private static int insertPos;
 46	private static int insertOffset;
 47	
 48	// Unfortunately, this does not work, as this DataFlavor is internally changed into another DataFlavor which does not match the intented DataFlavor anymore. :-( So, below, we are iterating.
 49	/*
 50	protected static DataFlavor	textURIlistDataFlavor = null;
 51	
 52	static {
 53		try {
 54			textURIlistDataFlavor = new DataFlavor("text/uri-list;representationclass=java.lang.String");
 55		} catch (ClassNotFoundException e) {
 56			throw new RuntimeException("Cannot create DataFlavor. This should not happen.",e);
 57		}
 58	}
 59	*/
 60
 61	//{{{ createTransferable
 62	protected Transferable createTransferable(JComponent c)
 63	{
 64		Log.log(Log.DEBUG,this,"createTransferable()");
 65		JEditTextArea textArea = (JEditTextArea)c;
 66		if(textArea.getSelectionCount() == 0)
 67			return null;
 68		else
 69		{
 70			dragSource = textArea;
 71			return new TextAreaSelection(textArea);
 72		}
 73	} //}}}
 74
 75	//{{{ getSourceActions
 76	public int getSourceActions(JComponent c)
 77	{
 78		return COPY_OR_MOVE;
 79	} //}}}
 80
 81	//{{{ importData
 82	public boolean importData(JComponent c, Transferable t)
 83	{
 84		Log.log(Log.DEBUG,this,"Import data");
 85//		Log.log(Log.DEBUG,this,"Import data: t.isDataFlavorSupported("+textURIlistDataFlavor+")="+t.isDataFlavorSupported(textURIlistDataFlavor)+".");
 86		if(!canImport(c,t.getTransferDataFlavors()))
 87			return false;
 88
 89		boolean returnValue;
 90
 91		try
 92		{
 93			if(t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
 94			{
 95				returnValue = importFile(c,t);
 96			}
 97			else {
 98				DataFlavor	uriListStringDataFlavor = null;
 99				DataFlavor[]	dataFlavors		= t.getTransferDataFlavors();
100				
101				for (int i = 0;i<dataFlavors.length;i++) {
102					DataFlavor dataFlavor = dataFlavors[i];
103					if (dataFlavor.getPrimaryType().equals("text")&&dataFlavor.getSubType().equals("uri-list")&&(dataFlavor.getRepresentationClass()==String.class)) {
104						uriListStringDataFlavor = dataFlavor;
105						break;
106					}
107 				}
108				
109				if ((uriListStringDataFlavor!=null)&&t.isDataFlavorSupported(uriListStringDataFlavor))
110				{
111					returnValue = importURIList(c,t,uriListStringDataFlavor);
112				}
113				else
114				{
115					returnValue = importText(c,t);
116				}
117			}
118		}
119		catch(Exception e)
120		{
121			Log.log(Log.ERROR,this,e);
122			returnValue = false;
123		}
124
125		GUIUtilities.getView(c).toFront();
126		GUIUtilities.getView(c).requestFocus();
127		c.requestFocus();
128
129		return returnValue;
130	} //}}}
131
132	//{{{ importFile
133	private boolean importFile(JComponent c, Transferable t)
134		throws Exception
135	{
136		Log.log(Log.DEBUG,this,"=> File list");
137		EditPane editPane = (EditPane)
138			GUIUtilities.getComponentParent(
139			c,EditPane.class);
140
141		Buffer buffer = null;
142
143		Object data = t.getTransferData(
144			DataFlavor.javaFileListFlavor);
145
146		Iterator iterator = ((List)data)
147			.iterator();
148
149		while(iterator.hasNext())
150		{
151			File file = (File)
152				iterator.next();
153			Buffer _buffer = jEdit.openFile(null,
154				file.getPath());
155			if(_buffer != null)
156				buffer = _buffer;
157		}
158
159		if(buffer != null)
160			editPane.setBuffer(buffer);
161		editPane.getView().toFront();
162		editPane.getView().requestFocus();
163		editPane.requestFocus();
164
165		return true;
166	} //}}}
167
168	//{{{ importText
169	private boolean importURIList(JComponent c, Transferable t,DataFlavor uriListStringDataFlavor)
170		throws Exception
171	{
172		String str = (String) t.getTransferData(uriListStringDataFlavor);
173
174		Log.log(Log.DEBUG,this,"=> URIList \""+str+"\"");
175		
176		JEditTextArea textArea = (JEditTextArea) c;
177		if (dragSource == null)
178		{
179			String		maybeManyFileURI	= str;
180			boolean		found			= false;			
181			String[]	components		= str.split("\r\n");
182			
183			for (int i = 0;i<components.length;i++)
184			{
185				String	str0	= components[i];
186				
187				if (str0.length()>0) {
188					URI	uri	= new URI(str0); // this handles the URI-decoding
189					
190					if ("file".equals(uri.getScheme()))
191					{
192						org.gjt.sp.jedit.io.VFSManager.runInWorkThread(new DraggedURLLoader(textArea,uri.getPath()));
193						found = true;
194					}
195					else
196					{
197						Log.log(Log.DEBUG,this,"I do not know how to handle this URI "+uri+", ignoring.");
198					}
199				}
200				else
201				{
202					// This should be the last component, because every URI in the list is terminated with a "\r\n", even the last one.
203					if (i!=components.length-1)
204					{
205						Log.log(Log.DEBUG,this,"Odd: there is an empty line in the uri list which is not the last line.");
206					}
207				}
208			}
209			
210			if (found)
211			{
212				return true;
213			}
214		}
215		
216		return true;
217	}
218	
219	//{{{ importText
220	private boolean importText(JComponent c, Transferable t)
221		throws Exception
222	{
223		String str = (String)t.getTransferData(
224			DataFlavor.stringFlavor);
225		str = str.trim();
226		Log.log(Log.DEBUG,this,"=> String \""+str+"\"");
227		
228		JEditTextArea textArea = (JEditTextArea)c;
229		if (dragSource == null)
230		{
231			String		maybeManyFileNames	= str;
232			boolean		found			= false;			
233			String[]	components		= str.split("\n");
234			
235			for (int i = 0;i<components.length;i++)
236			{
237				String str0 = components[i];
238				// Only examine the string for a URL if it came from
239				// outside of jEdit.
240				org.gjt.sp.jedit.io.VFS vfs = org.gjt.sp.jedit.io.VFSManager.getVFSForPath(str0);
241				if (!(vfs instanceof org.gjt.sp.jedit.io.FileVFS) || str.startsWith("file://"))
242				{
243				
244//					str = str.replace('\n',' ').replace('\r',' ').trim();
245					if (str0.startsWith("file://"))
246					{
247						str0 = str0.substring(7);
248					}
249					
250					org.gjt.sp.jedit.io.VFSManager.runInWorkThread(new DraggedURLLoader(textArea,str0));
251				}
252				found = true;
253				
254			}
255			
256			if (found) {
257				return true;
258			}
259		}
260
261		if(dragSource != null
262			&& textArea.getBuffer()
263			== dragSource.getBuffer())
264		{
265			compoundEdit = true;
266			textArea.getBuffer().beginCompoundEdit();
267		}
268		
269		
270		sameTextArea = (textArea == dragSource);
271
272		int caret = textArea.getCaretPosition();
273		Selection s = textArea.getSelectionAtOffset(caret);
274
275		/* if user drops into the same
276		selection where they started, do
277		nothing. */
278		if(s != null)
279		{
280			if(sameTextArea)
281				return false;
282			/* if user drops into a selection,
283			replace selection */
284			int startPos = s.start;
285			textArea.setSelectedText(s,str);
286			textArea.setSelection(new Selection.Range(startPos,startPos+str.length()));
287		}
288		/* otherwise just insert the text */
289		else
290		{
291			if (sameTextArea)
292			{
293				insertPos = caret;
294				insertOffset = 0;
295				Selection[] selections = textArea.getSelection();
296				for (int i=0;i<selections.length;i++)
297				{
298					if (selections[i].end<(insertPos+insertOffset))
299						insertOffset-=(selections[i].end-selections[i].start);
300				}
301			}
302			else
303			{
304				textArea.getBuffer().insert(caret,str);
305				textArea.setSelection(new Selection.Range(caret,caret+str.length()));
306			}
307		}
308		textArea.scrollToCaret(true);
309
310		return true;
311	} //}}}
312
313	//{{{ exportDone
314	protected void exportDone(JComponent c, Transferable t,
315		int action)
316	{
317		Log.log(Log.DEBUG,this,"Export done");
318
319		JEditTextArea textArea = (JEditTextArea)c;
320
321		try
322		{
323			// This happens if importData returns false. For example if you drop into the Selection
324			if (action == NONE)
325			{
326				Log.log(Log.DEBUG,this,"Export impossible");
327				return;
328			}
329
330			if(t == null)
331			{
332				Log.log(Log.DEBUG,this,"=> Null transferrable");
333				textArea.selectNone();
334			}
335			else if(t.isDataFlavorSupported(
336				DataFlavor.stringFlavor))
337			{
338				Log.log(Log.DEBUG,this,"=> String");
339				if (sameTextArea)
340				{
341					if(action == MOVE)
342					{
343						textArea.setSelectedText(null,false);
344						insertPos += insertOffset;
345					} 
346					try
347					{
348						String str = (String)t.getTransferData(DataFlavor.stringFlavor);
349						textArea.getBuffer().insert(insertPos,str);
350						textArea.setSelection(new Selection.Range(insertPos,insertPos+str.length()));
351					}
352					catch(Exception e)
353					{
354						Log.log(Log.DEBUG,this,"exportDone in sameTextArea");
355						Log.log(Log.DEBUG,this,e);
356					}
357				}
358				else
359				{
360					if(action == MOVE)
361						textArea.setSelectedText(null,false);
362					else
363						textArea.selectNone();
364				}
365			}
366		}
367		finally
368		{
369			if(compoundEdit)
370			{
371				compoundEdit = false;
372				textArea.getBuffer().endCompoundEdit();
373			}
374		}
375
376		dragSource = null;
377	} //}}}
378
379	//{{{ canImport
380	public boolean canImport(JComponent c, DataFlavor[] flavors)
381	{
382		JEditTextArea textArea = (JEditTextArea)c;
383
384		// correctly handle text flavor + file list flavor
385		// + text area read only, do an or of all flags
386		boolean returnValue = false;
387
388		for(int i = 0; i < flavors.length; i++)
389		{
390			if(flavors[i].equals(
391				DataFlavor.javaFileListFlavor))
392			{
393				returnValue = true;
394			}
395			else if(flavors[i].equals(
396				DataFlavor.stringFlavor))
397			{
398				if(textArea.isEditable())
399					returnValue = true;
400			}
401		}
402
403		Log.log(Log.DEBUG,this,"canImport() returning "
404			+ returnValue);
405		return returnValue;
406	} //}}}
407
408	//{{{ TextAreaSelection class
409	static class TextAreaSelection extends StringSelection
410	{
411		JEditTextArea textArea;
412
413		TextAreaSelection(JEditTextArea textArea)
414		{
415			super(textArea.getSelectedText());
416			this.textArea = textArea;
417		}
418	} //}}}
419
420	//{{{ DraggedURLLoader
421	class DraggedURLLoader extends org.gjt.sp.util.WorkRequest
422	{
423		private JEditTextArea textArea;
424		private String url;
425		
426		public DraggedURLLoader(JEditTextArea textArea, String url)
427		{
428			super();
429			this.textArea = textArea;
430			this.url = url;
431		}
432		public void run()
433		{
434			jEdit.openFile(textArea.getView(),url);
435		}
436	} //}}}
437
438}