blob: bdf80997af65d32225b1e6331225a32b6b0f2fb2 [file] [log] [blame]
/*
* Copyright 2000-2011 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.ide;
import com.intellij.openapi.editor.Document;
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.lang.ref.WeakReference;
/**
* This class represents usual {@link StringSelection transferable string} with additional meta-information that describes the place
* of the document that from there it was retrieved.
* <p/>
* The main idea is that we want to be able to combine adjacent text into single unit like
* <a href="http://www.gnu.org/software/emacs/manual/html_node/emacs/Kill-Ring.html#Kill-Ring">emacs kill ring</a> does.
* E.g. if the user invokes 'cut to the line end' subsequently we may want to paste all of them, hence, we need to be able
* to distinguish if particular copy-paste strings are adjacent.
* <p/>
* Thread-safe.
*
* @author Denis Zhdanov
* @since 4/15/11 6:29 PM
*/
public class KillRingTransferable implements Transferable {
private static final DataFlavor[] DATA_FLAVORS = {DataFlavor.stringFlavor};
private final String myData;
private final WeakReference<Document> myDocument;
private final int myStartOffset;
private final int myEndOffset;
private final boolean myCut;
private volatile boolean myReadyToCombine = true;
/**
* Creates new <code>KillRingTransferable</code> object.
*
* @param data target text to transfer
* @param document document that contained given text
* @param startOffset start offset of the given text at the given document
* @param endOffset end offset of the given text during current object construction
* @param cut flag that identifies whether target text was cut or copied from the document
*/
public KillRingTransferable(@NotNull String data,
@NotNull Document document,
int startOffset,
int endOffset,
boolean cut)
{
myData = data;
myDocument = new WeakReference<Document>(document);
myStartOffset = startOffset;
myEndOffset = endOffset;
myCut = cut;
}
@Override
public DataFlavor[] getTransferDataFlavors() {
return DATA_FLAVORS;
}
@Override
public boolean isDataFlavorSupported(DataFlavor flavor) {
return flavor == DataFlavor.stringFlavor;
}
@Nullable
@Override
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
return isDataFlavorSupported(flavor) ? myData : null;
}
@Nullable
public Document getDocument() {
return myDocument.get();
}
public int getStartOffset() {
return myStartOffset;
}
/**
* @return offset of the target text end on the moment of the current object construction
*/
public int getEndOffset() {
return myEndOffset;
}
public boolean isCut() {
return myCut;
}
/**
* @return <code>true</code> if current object can be combined with adjacent text; <code>false</code> otherwise.
* Default value is <code>true</code>
*/
public boolean isReadyToCombine() {
return myReadyToCombine;
}
/**
* Allows to define if current object can be combined with adjacent text.
*
* @param readyToCombine <code>true</code> if current object can be combined with adjacent text; <code>false</code> otherwise
*/
public void setReadyToCombine(boolean readyToCombine) {
myReadyToCombine = readyToCombine;
}
@Override
public String toString() {
return "data='" + myData + "', startOffset=" + myStartOffset + ", endOffset=" + myEndOffset +", cut=" + myCut;
}
}