2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com
.intellij
.ide
;
19 import com
.intellij
.openapi
.components
.ServiceManager
;
20 import com
.intellij
.openapi
.diagnostic
.Logger
;
21 import com
.intellij
.openapi
.ide
.CopyPasteManager
;
22 import com
.intellij
.openapi
.util
.Comparing
;
23 import com
.intellij
.openapi
.util
.text
.StringUtil
;
24 import com
.intellij
.openapi
.vfs
.LocalFileSystem
;
25 import com
.intellij
.openapi
.vfs
.VirtualFile
;
26 import com
.intellij
.psi
.*;
27 import org
.jetbrains
.annotations
.Nullable
;
29 import java
.awt
.datatransfer
.DataFlavor
;
30 import java
.awt
.datatransfer
.StringSelection
;
31 import java
.awt
.datatransfer
.Transferable
;
32 import java
.awt
.datatransfer
.UnsupportedFlavorException
;
34 import java
.io
.IOException
;
35 import java
.util
.ArrayList
;
36 import java
.util
.List
;
38 public class PsiCopyPasteManager
{
39 public static PsiCopyPasteManager
getInstance() {
40 return ServiceManager
.getService(PsiCopyPasteManager
.class);
43 private static final Logger LOG
= Logger
.getInstance("#com.intellij.ide.PsiCopyPasteManagerImpl");
45 private MyData myRecentData
;
46 private final CopyPasteManagerEx myCopyPasteManager
;
48 public PsiCopyPasteManager(CopyPasteManager copyPasteManager
) {
49 myCopyPasteManager
= (CopyPasteManagerEx
) copyPasteManager
;
53 public PsiElement
[] getElements(boolean[] isCopied
) {
55 Transferable content
= myCopyPasteManager
.getSystemClipboardContents();
58 transferData
= content
.getTransferData(ourDataFlavor
);
59 } catch (UnsupportedFlavorException e
) {
61 } catch (IOException e
) {
65 if (!(transferData
instanceof MyData
)) {
68 MyData dataProxy
= (MyData
) transferData
;
69 if (!Comparing
.equal(dataProxy
, myRecentData
)) {
72 if (isCopied
!= null) {
73 isCopied
[0] = myRecentData
.isCopied();
75 return myRecentData
.getElements();
76 } catch (Exception e
) {
77 if (LOG
.isDebugEnabled()) {
85 static PsiElement
[] getElements(final Transferable content
) {
86 if (content
== null) return null;
89 transferData
= content
.getTransferData(ourDataFlavor
);
90 } catch (UnsupportedFlavorException e
) {
92 } catch (IOException e
) {
96 return transferData
instanceof MyData ?
((MyData
)transferData
).getElements() : null;
100 Transferable old
= myCopyPasteManager
.getContents();
102 myCopyPasteManager
.setSystemClipboardContent(new StringSelection(""));
103 myCopyPasteManager
.fireContentChanged(old
);
106 public void setElements(PsiElement
[] elements
, boolean copied
) {
107 Transferable old
= myCopyPasteManager
.getContents();
108 myRecentData
= new MyData(elements
, copied
);
109 myCopyPasteManager
.setSystemClipboardContent(new MyTransferable(myRecentData
));
110 myCopyPasteManager
.fireContentChanged(old
);
113 public boolean isCutElement(Object element
) {
114 if (myRecentData
== null) return false;
115 if (myRecentData
.isCopied()) return false;
116 PsiElement
[] elements
= myRecentData
.getElements();
117 if (elements
== null) return false;
118 for (PsiElement aElement
: elements
) {
119 if (aElement
== element
) return true;
124 private static final DataFlavor ourDataFlavor
;
128 final Class
<MyData
> flavorClass
= MyData
.class;
129 final Thread currentThread
= Thread
.currentThread();
130 final ClassLoader currentLoader
= currentThread
.getContextClassLoader();
132 currentThread
.setContextClassLoader(flavorClass
.getClassLoader());
133 ourDataFlavor
= new DataFlavor(DataFlavor
.javaJVMLocalObjectMimeType
+ ";class=" + flavorClass
.getName());
136 currentThread
.setContextClassLoader(currentLoader
);
139 catch (ClassNotFoundException e
) {
140 throw new RuntimeException(e
);
145 private static class MyData
{
146 private PsiElement
[] myElements
;
147 private final boolean myIsCopied
;
149 public MyData(PsiElement
[] elements
, boolean copied
) {
150 myElements
= elements
;
154 public PsiElement
[] getElements() {
155 if (myElements
== null) return PsiElement
.EMPTY_ARRAY
;
157 int validElementsCount
= 0;
159 for (PsiElement element
: myElements
) {
160 if (element
.isValid()) {
161 validElementsCount
++;
165 if (validElementsCount
== myElements
.length
) {
169 PsiElement
[] validElements
= new PsiElement
[validElementsCount
];
171 for (PsiElement element
: myElements
) {
172 if (element
.isValid()) {
173 validElements
[j
++] = element
;
177 myElements
= validElements
;
181 public boolean isCopied() {
186 public static class MyTransferable
implements Transferable
{
187 private final MyData myDataProxy
;
188 private static final DataFlavor
[] DATA_FLAVOR_ARRAY
= new DataFlavor
[]{ourDataFlavor
, DataFlavor
.stringFlavor
, DataFlavor
.javaFileListFlavor
};
190 public MyTransferable(MyData data
) {
194 public Object
getTransferData(DataFlavor flavor
) throws UnsupportedFlavorException
, IOException
{
195 if (ourDataFlavor
.equals(flavor
)) {
198 if (DataFlavor
.stringFlavor
.equals(flavor
)) {
199 return getDataAsText();
201 if (DataFlavor
.javaFileListFlavor
.equals(flavor
)) {
202 return asFileList(myDataProxy
.getElements());
208 private String
getDataAsText() {
209 List
<String
> names
= new ArrayList
<String
>();
210 for (PsiElement element
: myDataProxy
.getElements()) {
211 if (element
instanceof PsiNamedElement
) {
212 String name
= ((PsiNamedElement
) element
).getName();
218 if (names
.isEmpty()) {
221 return StringUtil
.join(names
, "\n");
225 public DataFlavor
[] getTransferDataFlavors() {
226 return DATA_FLAVOR_ARRAY
;
229 public boolean isDataFlavorSupported(DataFlavor flavor
) {
230 return flavor
.equals(ourDataFlavor
) || flavor
.equals(DataFlavor
.stringFlavor
) || flavor
.equals(DataFlavor
.javaFileListFlavor
);
233 public PsiElement
[] getElements() {
234 return myDataProxy
.getElements();
238 public static List
<File
> asFileList(final PsiElement
[] elements
) {
239 List
<File
> result
= new ArrayList
<File
>();
240 for (PsiElement element
: elements
) {
241 final PsiFileSystemItem psiFile
;
242 if (element
instanceof PsiFileSystemItem
) {
243 psiFile
= (PsiFileSystemItem
)element
;
245 else if (element
instanceof PsiDirectoryContainer
) {
246 final PsiDirectory
[] directories
= ((PsiDirectoryContainer
)element
).getDirectories();
247 psiFile
= directories
[0];
250 psiFile
= element
.getContainingFile();
252 if (psiFile
!= null) {
253 VirtualFile vFile
= psiFile
.getVirtualFile();
254 if (vFile
!= null && vFile
.getFileSystem() instanceof LocalFileSystem
) {
255 result
.add(new File(vFile
.getPath()));
259 if (result
.isEmpty()) {