| /* |
| * Copyright 2000-2014 JetBrains s.r.o. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package com.intellij.openapi.editor.impl; |
| |
| import com.intellij.codeInsight.editorActions.TextBlockTransferable; |
| import com.intellij.codeInsight.editorActions.TextBlockTransferableData; |
| import com.intellij.openapi.application.ApplicationManager; |
| import com.intellij.openapi.diagnostic.Logger; |
| import com.intellij.openapi.editor.*; |
| import com.intellij.openapi.ide.CopyPasteManager; |
| import com.intellij.openapi.util.TextRange; |
| import com.intellij.openapi.util.text.LineTokenizer; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import java.awt.datatransfer.DataFlavor; |
| import java.awt.datatransfer.StringSelection; |
| import java.awt.datatransfer.Transferable; |
| import java.awt.datatransfer.UnsupportedFlavorException; |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Iterator; |
| import java.util.List; |
| |
| public class EditorCopyPasteHelperImpl extends EditorCopyPasteHelper { |
| private static final Logger LOG = Logger.getInstance(EditorCopyPasteHelperImpl.class); |
| |
| @Override |
| public void copySelectionToClipboard(@NotNull Editor editor) { |
| ApplicationManager.getApplication().assertIsDispatchThread(); |
| List<TextBlockTransferableData> extraData = new ArrayList<TextBlockTransferableData>(); |
| String s = editor.getCaretModel().supportsMultipleCarets() ? getSelectedTextForClipboard(editor, extraData) |
| : editor.getSelectionModel().getSelectedText(); |
| if (s == null) return; |
| |
| s = TextBlockTransferable.convertLineSeparators(s, "\n", extraData); |
| Transferable contents = editor.getCaretModel().supportsMultipleCarets() ? new TextBlockTransferable(s, extraData, null) : new StringSelection(s); |
| CopyPasteManager.getInstance().setContents(contents); |
| } |
| |
| public static String getSelectedTextForClipboard(@NotNull Editor editor, @NotNull Collection<TextBlockTransferableData> extraDataCollector) { |
| final StringBuilder buf = new StringBuilder(); |
| String separator = ""; |
| List<Caret> carets = editor.getCaretModel().getAllCarets(); |
| int[] startOffsets = new int[carets.size()]; |
| int[] endOffsets = new int[carets.size()]; |
| for (int i = 0; i < carets.size(); i++) { |
| buf.append(separator); |
| String caretSelectedText = carets.get(i).getSelectedText(); |
| startOffsets[i] = buf.length(); |
| if (caretSelectedText != null) { |
| buf.append(caretSelectedText); |
| } |
| endOffsets[i] = buf.length(); |
| separator = "\n"; |
| } |
| extraDataCollector.add(new CaretStateTransferableData(startOffsets, endOffsets)); |
| return buf.toString(); |
| } |
| |
| @Nullable |
| @Override |
| public TextRange[] pasteFromClipboard(@NotNull Editor editor) { |
| CopyPasteManager manager = CopyPasteManager.getInstance(); |
| if (manager.areDataFlavorsAvailable(DataFlavor.stringFlavor)) { |
| Transferable clipboardContents = manager.getContents(); |
| if (clipboardContents != null) { |
| return pasteTransferable(editor, clipboardContents); |
| } |
| } |
| return null; |
| } |
| |
| @Nullable |
| @Override |
| public TextRange[] pasteTransferable(final @NotNull Editor editor, @NotNull Transferable content) { |
| String text = getStringContent(content); |
| if (text == null) return null; |
| |
| if (editor.getCaretModel().supportsMultipleCarets()) { |
| int caretCount = editor.getCaretModel().getCaretCount(); |
| if (caretCount == 1 && editor.isColumnMode()) { |
| int pastedLineCount = LineTokenizer.calcLineCount(text, true); |
| EditorModificationUtil.deleteSelectedText(editor); |
| Caret caret = editor.getCaretModel().getPrimaryCaret(); |
| for (int i = 0; i < pastedLineCount - 1; i++) { |
| caret = caret.clone(false); |
| if (caret == null) { |
| break; |
| } |
| } |
| caretCount = editor.getCaretModel().getCaretCount(); |
| } |
| CaretStateTransferableData caretData = null; |
| try { |
| caretData = content.isDataFlavorSupported(CaretStateTransferableData.FLAVOR) |
| ? (CaretStateTransferableData)content.getTransferData(CaretStateTransferableData.FLAVOR) : null; |
| } |
| catch (Exception e) { |
| LOG.error(e); |
| } |
| final TextRange[] ranges = new TextRange[caretCount]; |
| final Iterator<String> segments = new ClipboardTextPerCaretSplitter().split(text, caretData, caretCount).iterator(); |
| final int[] index = {0}; |
| editor.getCaretModel().runForEachCaret(new CaretAction() { |
| @Override |
| public void perform(Caret caret) { |
| String segment = segments.next(); |
| int caretOffset = caret.getOffset(); |
| ranges[index[0]++] = new TextRange(caretOffset, caretOffset + segment.length()); |
| EditorModificationUtil.insertStringAtCaret(editor, segment, false, true); |
| } |
| }); |
| return ranges; |
| } |
| else { |
| int caretOffset = editor.getCaretModel().getOffset(); |
| EditorModificationUtil.insertStringAtCaret(editor, text, false, true); |
| return new TextRange[] { new TextRange(caretOffset, caretOffset + text.length())}; |
| } |
| } |
| |
| @Nullable |
| private static String getStringContent(@NotNull Transferable content) { |
| RawText raw = RawText.fromTransferable(content); |
| if (raw != null) return raw.rawText; |
| |
| try { |
| return (String)content.getTransferData(DataFlavor.stringFlavor); |
| } |
| catch (UnsupportedFlavorException ignore) { } |
| catch (IOException ignore) { } |
| |
| return null; |
| } |
| } |