ComponentWithBrowseButton - optional remove listener on hide
[fedora-idea.git] / platform / lang-impl / src / com / intellij / ide / PsiCopyPasteManager.java
blob799a6fb0a5b5f46d7f6bec97526701177ac6666a
1 /*
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;
33 import java.io.File;
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;
52 @Nullable
53 public PsiElement[] getElements(boolean[] isCopied) {
54 try {
55 Transferable content = myCopyPasteManager.getSystemClipboardContents();
56 Object transferData;
57 try {
58 transferData = content.getTransferData(ourDataFlavor);
59 } catch (UnsupportedFlavorException e) {
60 return null;
61 } catch (IOException e) {
62 return null;
65 if (!(transferData instanceof MyData)) {
66 return null;
68 MyData dataProxy = (MyData) transferData;
69 if (!Comparing.equal(dataProxy, myRecentData)) {
70 return null;
72 if (isCopied != null) {
73 isCopied[0] = myRecentData.isCopied();
75 return myRecentData.getElements();
76 } catch (Exception e) {
77 if (LOG.isDebugEnabled()) {
78 LOG.debug(e);
80 return null;
84 @Nullable
85 static PsiElement[] getElements(final Transferable content) {
86 if (content == null) return null;
87 Object transferData;
88 try {
89 transferData = content.getTransferData(ourDataFlavor);
90 } catch (UnsupportedFlavorException e) {
91 return null;
92 } catch (IOException e) {
93 return null;
96 return transferData instanceof MyData ? ((MyData)transferData).getElements() : null;
99 public void clear() {
100 Transferable old = myCopyPasteManager.getContents();
101 myRecentData = null;
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;
121 return false;
124 private static final DataFlavor ourDataFlavor;
126 static {
127 try {
128 final Class<MyData> flavorClass = MyData.class;
129 final Thread currentThread = Thread.currentThread();
130 final ClassLoader currentLoader = currentThread.getContextClassLoader();
131 try {
132 currentThread.setContextClassLoader(flavorClass.getClassLoader());
133 ourDataFlavor = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType + ";class=" + flavorClass.getName());
135 finally {
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;
151 myIsCopied = copied;
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) {
166 return myElements;
169 PsiElement[] validElements = new PsiElement[validElementsCount];
170 int j=0;
171 for (PsiElement element : myElements) {
172 if (element.isValid()) {
173 validElements[j++] = element;
177 myElements = validElements;
178 return myElements;
181 public boolean isCopied() {
182 return myIsCopied;
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) {
191 myDataProxy = data;
194 public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
195 if (ourDataFlavor.equals(flavor)) {
196 return myDataProxy;
198 if (DataFlavor.stringFlavor.equals(flavor)) {
199 return getDataAsText();
201 if (DataFlavor.javaFileListFlavor.equals(flavor)) {
202 return asFileList(myDataProxy.getElements());
204 return null;
207 @Nullable
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();
213 if (name != null) {
214 names.add(name);
218 if (names.isEmpty()) {
219 return null;
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];
249 else {
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()) {
260 return null;
262 return result;