PageRenderTime 43ms CodeModel.GetById 19ms RepoModel.GetById 1ms 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. package org.gjt.sp.jedit.textarea;
  23. //{{{ Imports
  24. import javax.swing.*;
  25. import java.awt.datatransfer.*;
  26. import java.io.File;
  27. import java.util.Iterator;
  28. import java.util.List;
  29. import java.net.URI;
  30. import org.gjt.sp.jedit.Buffer;
  31. import org.gjt.sp.jedit.EditPane;
  32. import org.gjt.sp.jedit.GUIUtilities;
  33. import org.gjt.sp.jedit.jEdit;
  34. import org.gjt.sp.util.Log;
  35. //}}}
  36. class TextAreaTransferHandler extends TransferHandler
  37. {
  38. /* I assume that there can be only one drag operation at the time */
  39. private static JEditTextArea dragSource;
  40. private static boolean compoundEdit;
  41. private static boolean sameTextArea;
  42. private static int insertPos;
  43. private static int insertOffset;
  44. // 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.
  45. /*
  46. protected static DataFlavor textURIlistDataFlavor = null;
  47. static {
  48. try {
  49. textURIlistDataFlavor = new DataFlavor("text/uri-list;representationclass=java.lang.String");
  50. } catch (ClassNotFoundException e) {
  51. throw new RuntimeException("Cannot create DataFlavor. This should not happen.",e);
  52. }
  53. }
  54. */
  55. //{{{ createTransferable
  56. protected Transferable createTransferable(JComponent c)
  57. {
  58. Log.log(Log.DEBUG,this,"createTransferable()");
  59. JEditTextArea textArea = (JEditTextArea)c;
  60. if(textArea.getSelectionCount() == 0)
  61. return null;
  62. else
  63. {
  64. dragSource = textArea;
  65. return new TextAreaSelection(textArea);
  66. }
  67. } //}}}
  68. //{{{ getSourceActions
  69. public int getSourceActions(JComponent c)
  70. {
  71. return COPY_OR_MOVE;
  72. } //}}}
  73. //{{{ importData
  74. public boolean importData(JComponent c, Transferable t)
  75. {
  76. Log.log(Log.DEBUG,this,"Import data");
  77. // Log.log(Log.DEBUG,this,"Import data: t.isDataFlavorSupported("+textURIlistDataFlavor+")="+t.isDataFlavorSupported(textURIlistDataFlavor)+".");
  78. if(!canImport(c,t.getTransferDataFlavors()))
  79. return false;
  80. boolean returnValue;
  81. try
  82. {
  83. if(t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
  84. {
  85. returnValue = importFile(c,t);
  86. }
  87. else {
  88. DataFlavor uriListStringDataFlavor = null;
  89. DataFlavor[] dataFlavors = t.getTransferDataFlavors();
  90. for (int i = 0;i<dataFlavors.length;i++) {
  91. DataFlavor dataFlavor = dataFlavors[i];
  92. if (dataFlavor.getPrimaryType().equals("text")&&dataFlavor.getSubType().equals("uri-list")&&(dataFlavor.getRepresentationClass()==String.class)) {
  93. uriListStringDataFlavor = dataFlavor;
  94. break;
  95. }
  96. }
  97. if ((uriListStringDataFlavor!=null)&&t.isDataFlavorSupported(uriListStringDataFlavor))
  98. {
  99. returnValue = importURIList(c,t,uriListStringDataFlavor);
  100. }
  101. else
  102. {
  103. returnValue = importText(c,t);
  104. }
  105. }
  106. }
  107. catch(Exception e)
  108. {
  109. Log.log(Log.ERROR,this,e);
  110. returnValue = false;
  111. }
  112. GUIUtilities.getView(c).toFront();
  113. GUIUtilities.getView(c).requestFocus();
  114. c.requestFocus();
  115. return returnValue;
  116. } //}}}
  117. //{{{ importFile
  118. private boolean importFile(JComponent c, Transferable t)
  119. throws Exception
  120. {
  121. Log.log(Log.DEBUG,this,"=> File list");
  122. EditPane editPane = (EditPane)
  123. GUIUtilities.getComponentParent(
  124. c,EditPane.class);
  125. Buffer buffer = null;
  126. Object data = t.getTransferData(
  127. DataFlavor.javaFileListFlavor);
  128. Iterator iterator = ((List)data)
  129. .iterator();
  130. while(iterator.hasNext())
  131. {
  132. File file = (File)
  133. iterator.next();
  134. Buffer _buffer = jEdit.openFile(null,
  135. file.getPath());
  136. if(_buffer != null)
  137. buffer = _buffer;
  138. }
  139. if(buffer != null)
  140. editPane.setBuffer(buffer);
  141. editPane.getView().toFront();
  142. editPane.getView().requestFocus();
  143. editPane.requestFocus();
  144. return true;
  145. } //}}}
  146. //{{{ importText
  147. private boolean importURIList(JComponent c, Transferable t,DataFlavor uriListStringDataFlavor)
  148. throws Exception
  149. {
  150. String str = (String) t.getTransferData(uriListStringDataFlavor);
  151. Log.log(Log.DEBUG,this,"=> URIList \""+str+"\"");
  152. JEditTextArea textArea = (JEditTextArea) c;
  153. if (dragSource == null)
  154. {
  155. String maybeManyFileURI = str;
  156. boolean found = false;
  157. String[] components = str.split("\r\n");
  158. for (int i = 0;i<components.length;i++)
  159. {
  160. String str0 = components[i];
  161. if (str0.length()>0) {
  162. URI uri = new URI(str0); // this handles the URI-decoding
  163. if ("file".equals(uri.getScheme()))
  164. {
  165. org.gjt.sp.jedit.io.VFSManager.runInWorkThread(new DraggedURLLoader(textArea,uri.getPath()));
  166. found = true;
  167. }
  168. else
  169. {
  170. Log.log(Log.DEBUG,this,"I do not know how to handle this URI "+uri+", ignoring.");
  171. }
  172. }
  173. else
  174. {
  175. // This should be the last component, because every URI in the list is terminated with a "\r\n", even the last one.
  176. if (i!=components.length-1)
  177. {
  178. Log.log(Log.DEBUG,this,"Odd: there is an empty line in the uri list which is not the last line.");
  179. }
  180. }
  181. }
  182. if (found)
  183. {
  184. return true;
  185. }
  186. }
  187. return true;
  188. }
  189. //{{{ importText
  190. private boolean importText(JComponent c, Transferable t)
  191. throws Exception
  192. {
  193. String str = (String)t.getTransferData(
  194. DataFlavor.stringFlavor);
  195. str = str.trim();
  196. Log.log(Log.DEBUG,this,"=> String \""+str+"\"");
  197. JEditTextArea textArea = (JEditTextArea)c;
  198. if (dragSource == null)
  199. {
  200. String maybeManyFileNames = str;
  201. boolean found = false;
  202. String[] components = str.split("\n");
  203. for (int i = 0;i<components.length;i++)
  204. {
  205. String str0 = components[i];
  206. // Only examine the string for a URL if it came from
  207. // outside of jEdit.
  208. org.gjt.sp.jedit.io.VFS vfs = org.gjt.sp.jedit.io.VFSManager.getVFSForPath(str0);
  209. if (!(vfs instanceof org.gjt.sp.jedit.io.FileVFS) || str.startsWith("file://"))
  210. {
  211. // str = str.replace('\n',' ').replace('\r',' ').trim();
  212. if (str0.startsWith("file://"))
  213. {
  214. str0 = str0.substring(7);
  215. }
  216. org.gjt.sp.jedit.io.VFSManager.runInWorkThread(new DraggedURLLoader(textArea,str0));
  217. }
  218. found = true;
  219. }
  220. if (found) {
  221. return true;
  222. }
  223. }
  224. if(dragSource != null
  225. && textArea.getBuffer()
  226. == dragSource.getBuffer())
  227. {
  228. compoundEdit = true;
  229. textArea.getBuffer().beginCompoundEdit();
  230. }
  231. sameTextArea = (textArea == dragSource);
  232. int caret = textArea.getCaretPosition();
  233. Selection s = textArea.getSelectionAtOffset(caret);
  234. /* if user drops into the same
  235. selection where they started, do
  236. nothing. */
  237. if(s != null)
  238. {
  239. if(sameTextArea)
  240. return false;
  241. /* if user drops into a selection,
  242. replace selection */
  243. int startPos = s.start;
  244. textArea.setSelectedText(s,str);
  245. textArea.setSelection(new Selection.Range(startPos,startPos+str.length()));
  246. }
  247. /* otherwise just insert the text */
  248. else
  249. {
  250. if (sameTextArea)
  251. {
  252. insertPos = caret;
  253. insertOffset = 0;
  254. Selection[] selections = textArea.getSelection();
  255. for (int i=0;i<selections.length;i++)
  256. {
  257. if (selections[i].end<(insertPos+insertOffset))
  258. insertOffset-=(selections[i].end-selections[i].start);
  259. }
  260. }
  261. else
  262. {
  263. textArea.getBuffer().insert(caret,str);
  264. textArea.setSelection(new Selection.Range(caret,caret+str.length()));
  265. }
  266. }
  267. textArea.scrollToCaret(true);
  268. return true;
  269. } //}}}
  270. //{{{ exportDone
  271. protected void exportDone(JComponent c, Transferable t,
  272. int action)
  273. {
  274. Log.log(Log.DEBUG,this,"Export done");
  275. JEditTextArea textArea = (JEditTextArea)c;
  276. try
  277. {
  278. // This happens if importData returns false. For example if you drop into the Selection
  279. if (action == NONE)
  280. {
  281. Log.log(Log.DEBUG,this,"Export impossible");
  282. return;
  283. }
  284. if(t == null)
  285. {
  286. Log.log(Log.DEBUG,this,"=> Null transferrable");
  287. textArea.selectNone();
  288. }
  289. else if(t.isDataFlavorSupported(
  290. DataFlavor.stringFlavor))
  291. {
  292. Log.log(Log.DEBUG,this,"=> String");
  293. if (sameTextArea)
  294. {
  295. if(action == MOVE)
  296. {
  297. textArea.setSelectedText(null,false);
  298. insertPos += insertOffset;
  299. }
  300. try
  301. {
  302. String str = (String)t.getTransferData(DataFlavor.stringFlavor);
  303. textArea.getBuffer().insert(insertPos,str);
  304. textArea.setSelection(new Selection.Range(insertPos,insertPos+str.length()));
  305. }
  306. catch(Exception e)
  307. {
  308. Log.log(Log.DEBUG,this,"exportDone in sameTextArea");
  309. Log.log(Log.DEBUG,this,e);
  310. }
  311. }
  312. else
  313. {
  314. if(action == MOVE)
  315. textArea.setSelectedText(null,false);
  316. else
  317. textArea.selectNone();
  318. }
  319. }
  320. }
  321. finally
  322. {
  323. if(compoundEdit)
  324. {
  325. compoundEdit = false;
  326. textArea.getBuffer().endCompoundEdit();
  327. }
  328. }
  329. dragSource = null;
  330. } //}}}
  331. //{{{ canImport
  332. public boolean canImport(JComponent c, DataFlavor[] flavors)
  333. {
  334. JEditTextArea textArea = (JEditTextArea)c;
  335. // correctly handle text flavor + file list flavor
  336. // + text area read only, do an or of all flags
  337. boolean returnValue = false;
  338. for(int i = 0; i < flavors.length; i++)
  339. {
  340. if(flavors[i].equals(
  341. DataFlavor.javaFileListFlavor))
  342. {
  343. returnValue = true;
  344. }
  345. else if(flavors[i].equals(
  346. DataFlavor.stringFlavor))
  347. {
  348. if(textArea.isEditable())
  349. returnValue = true;
  350. }
  351. }
  352. Log.log(Log.DEBUG,this,"canImport() returning "
  353. + returnValue);
  354. return returnValue;
  355. } //}}}
  356. //{{{ TextAreaSelection class
  357. static class TextAreaSelection extends StringSelection
  358. {
  359. JEditTextArea textArea;
  360. TextAreaSelection(JEditTextArea textArea)
  361. {
  362. super(textArea.getSelectedText());
  363. this.textArea = textArea;
  364. }
  365. } //}}}
  366. //{{{ DraggedURLLoader
  367. class DraggedURLLoader extends org.gjt.sp.util.WorkRequest
  368. {
  369. private JEditTextArea textArea;
  370. private String url;
  371. public DraggedURLLoader(JEditTextArea textArea, String url)
  372. {
  373. super();
  374. this.textArea = textArea;
  375. this.url = url;
  376. }
  377. public void run()
  378. {
  379. jEdit.openFile(textArea.getView(),url);
  380. }
  381. } //}}}
  382. }