1 package com
.intellij
.ide
;
3 import com
.intellij
.openapi
.components
.ServiceManager
;
4 import com
.intellij
.openapi
.diagnostic
.Logger
;
5 import com
.intellij
.openapi
.ide
.CopyPasteManager
;
6 import com
.intellij
.openapi
.util
.Comparing
;
7 import com
.intellij
.openapi
.util
.text
.StringUtil
;
8 import com
.intellij
.openapi
.vfs
.LocalFileSystem
;
9 import com
.intellij
.openapi
.vfs
.VirtualFile
;
10 import com
.intellij
.psi
.PsiElement
;
11 import com
.intellij
.psi
.PsiFile
;
12 import com
.intellij
.psi
.PsiNamedElement
;
13 import org
.jetbrains
.annotations
.Nullable
;
15 import java
.awt
.datatransfer
.DataFlavor
;
16 import java
.awt
.datatransfer
.StringSelection
;
17 import java
.awt
.datatransfer
.Transferable
;
18 import java
.awt
.datatransfer
.UnsupportedFlavorException
;
20 import java
.io
.IOException
;
21 import java
.util
.ArrayList
;
22 import java
.util
.List
;
24 public class PsiCopyPasteManager
{
25 public static PsiCopyPasteManager
getInstance() {
26 return ServiceManager
.getService(PsiCopyPasteManager
.class);
29 private static final Logger LOG
= Logger
.getInstance("#com.intellij.ide.PsiCopyPasteManagerImpl");
31 private MyData myRecentData
;
32 private final CopyPasteManagerEx myCopyPasteManager
;
34 public PsiCopyPasteManager(CopyPasteManager copyPasteManager
) {
35 myCopyPasteManager
= (CopyPasteManagerEx
) copyPasteManager
;
39 public PsiElement
[] getElements(boolean[] isCopied
) {
41 Transferable content
= myCopyPasteManager
.getSystemClipboardContents();
44 transferData
= content
.getTransferData(ourDataFlavor
);
45 } catch (UnsupportedFlavorException e
) {
47 } catch (IOException e
) {
51 if (!(transferData
instanceof MyData
)) {
54 MyData dataProxy
= (MyData
) transferData
;
55 if (!Comparing
.equal(dataProxy
, myRecentData
)) {
58 if (isCopied
!= null) {
59 isCopied
[0] = myRecentData
.isCopied();
61 return myRecentData
.getElements();
62 } catch (Exception e
) {
63 if (LOG
.isDebugEnabled()) {
71 static PsiElement
[] getElements(final Transferable content
) {
72 if (content
== null) return null;
75 transferData
= content
.getTransferData(ourDataFlavor
);
76 } catch (UnsupportedFlavorException e
) {
78 } catch (IOException e
) {
82 return transferData
instanceof MyData ?
((MyData
)transferData
).getElements() : null;
86 Transferable old
= myCopyPasteManager
.getContents();
88 myCopyPasteManager
.setSystemClipboardContent(new StringSelection(""));
89 myCopyPasteManager
.fireContentChanged(old
);
92 public void setElements(PsiElement
[] elements
, boolean copied
) {
93 Transferable old
= myCopyPasteManager
.getContents();
94 myRecentData
= new MyData(elements
, copied
);
95 myCopyPasteManager
.setSystemClipboardContent(new MyTransferable(myRecentData
));
96 myCopyPasteManager
.fireContentChanged(old
);
99 public boolean isCutElement(Object element
) {
100 if (myRecentData
== null) return false;
101 if (myRecentData
.isCopied()) return false;
102 PsiElement
[] elements
= myRecentData
.getElements();
103 if (elements
== null) return false;
104 for (PsiElement aElement
: elements
) {
105 if (aElement
== element
) return true;
110 private static final DataFlavor ourDataFlavor
;
114 final Class
<MyData
> flavorClass
= MyData
.class;
115 final Thread currentThread
= Thread
.currentThread();
116 final ClassLoader currentLoader
= currentThread
.getContextClassLoader();
118 currentThread
.setContextClassLoader(flavorClass
.getClassLoader());
119 ourDataFlavor
= new DataFlavor(DataFlavor
.javaJVMLocalObjectMimeType
+ ";class=" + flavorClass
.getName());
122 currentThread
.setContextClassLoader(currentLoader
);
125 catch (ClassNotFoundException e
) {
126 throw new RuntimeException(e
);
131 private static class MyData
{
132 private PsiElement
[] myElements
;
133 private final boolean myIsCopied
;
135 public MyData(PsiElement
[] elements
, boolean copied
) {
136 myElements
= elements
;
140 public PsiElement
[] getElements() {
141 if (myElements
== null) return PsiElement
.EMPTY_ARRAY
;
143 int validElementsCount
= 0;
145 for (PsiElement element
: myElements
) {
146 if (element
.isValid()) {
147 validElementsCount
++;
151 if (validElementsCount
== myElements
.length
) {
155 PsiElement
[] validElements
= new PsiElement
[validElementsCount
];
157 for (PsiElement element
: myElements
) {
158 if (element
.isValid()) {
159 validElements
[j
++] = element
;
163 myElements
= validElements
;
167 public boolean isCopied() {
172 public static class MyTransferable
implements Transferable
{
173 private final MyData myDataProxy
;
174 private static final DataFlavor
[] DATA_FLAVOR_ARRAY
= new DataFlavor
[]{ourDataFlavor
, DataFlavor
.stringFlavor
, DataFlavor
.javaFileListFlavor
};
176 public MyTransferable(MyData data
) {
180 public Object
getTransferData(DataFlavor flavor
) throws UnsupportedFlavorException
, IOException
{
181 if (ourDataFlavor
.equals(flavor
)) {
184 if (DataFlavor
.stringFlavor
.equals(flavor
)) {
185 return getDataAsText();
187 if (DataFlavor
.javaFileListFlavor
.equals(flavor
)) {
188 return asFileList(myDataProxy
.getElements());
194 private String
getDataAsText() {
195 List
<String
> names
= new ArrayList
<String
>();
196 for (PsiElement element
: myDataProxy
.getElements()) {
197 if (element
instanceof PsiNamedElement
) {
198 String name
= ((PsiNamedElement
) element
).getName();
204 if (names
.isEmpty()) {
207 return StringUtil
.join(names
, "\n");
211 public DataFlavor
[] getTransferDataFlavors() {
212 return DATA_FLAVOR_ARRAY
;
215 public boolean isDataFlavorSupported(DataFlavor flavor
) {
216 return flavor
.equals(ourDataFlavor
) || flavor
.equals(DataFlavor
.stringFlavor
) || flavor
.equals(DataFlavor
.javaFileListFlavor
);
219 public PsiElement
[] getElements() {
220 return myDataProxy
.getElements();
224 public static List
<File
> asFileList(final PsiElement
[] elements
) {
225 List
<File
> result
= new ArrayList
<File
>();
226 for (PsiElement element
: elements
) {
227 final PsiFile psiFile
= element
.getContainingFile();
228 if (psiFile
!= null) {
229 VirtualFile vFile
= psiFile
.getVirtualFile();
230 if (vFile
!= null && vFile
.getFileSystem() instanceof LocalFileSystem
) {
231 result
.add(new File(vFile
.getPath()));
235 if (result
.isEmpty()) {