mirror of
https://github.com/SuspiciousActivity/ByteEdit.git
synced 2026-08-13 17:56:17 +00:00
Added source for ByteEdit
This commit is contained in:
1 parent
32dacb30ff
commit
d29e5765af
352 files changed
+199016
No files matched your search
@@ -0,0 +1,513 @@
|
||||
/*
|
||||
* 07/29/2004
|
||||
*
|
||||
* RTATextTransferHandler.java - Handles the transfer of data to/from an
|
||||
* RTextArea via drag-and-drop.
|
||||
*
|
||||
* This library is distributed under a modified BSD license. See the included
|
||||
* RSyntaxTextArea.License.txt file for details.
|
||||
*/
|
||||
package org.fife.ui.rtextarea;
|
||||
|
||||
import java.awt.datatransfer.DataFlavor;
|
||||
import java.awt.datatransfer.Transferable;
|
||||
import java.awt.datatransfer.UnsupportedFlavorException;
|
||||
import java.awt.im.InputContext;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
import java.io.StringBufferInputStream;
|
||||
import java.io.StringReader;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.TransferHandler;
|
||||
import javax.swing.text.BadLocationException;
|
||||
import javax.swing.text.Document;
|
||||
import javax.swing.text.JTextComponent;
|
||||
import javax.swing.text.Position;
|
||||
|
||||
|
||||
/**
|
||||
* Handles the transfer of data to/from an <code>RTextArea</code> via
|
||||
* drag-and-drop. This class is pretty much ripped off from a subclass of
|
||||
* <code>BasicTextUI</code>. In the future, it will include the ability to
|
||||
* drag-and-drop files into <code>RTextArea</code>s (i.e., the text will be
|
||||
* inserted into the text area).<p>
|
||||
*
|
||||
* The main reason this class is kept around is so we can subclass it.
|
||||
*
|
||||
* @author Robert Futrell
|
||||
* @version 0.1
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class RTATextTransferHandler extends TransferHandler {
|
||||
|
||||
private JTextComponent exportComp;
|
||||
private boolean shouldRemove;
|
||||
private int p0;
|
||||
private int p1;
|
||||
private boolean withinSameComponent;
|
||||
|
||||
|
||||
/**
|
||||
* Try to find a flavor that can be used to import a Transferable to a
|
||||
* specified text component.
|
||||
* The set of usable flavors are tried in the following order:
|
||||
* <ol>
|
||||
* <li>First, an attempt is made to find a flavor matching the content
|
||||
* tyep of the EditorKit for the component.
|
||||
* <li>Second, an attempt to find a text/plain flavor is made.
|
||||
* <li>Third, an attempt to find a flavor representing a String
|
||||
* reference in the same VM is made.
|
||||
* <li>Lastly, DataFlavor.stringFlavor is searched for.
|
||||
* </ol>
|
||||
*
|
||||
* @param flavors The flavors to check if c will accept them.
|
||||
* @param c The text component to see whether it will accept any of the
|
||||
* specified data flavors as input.
|
||||
*/
|
||||
protected DataFlavor getImportFlavor(DataFlavor[] flavors,
|
||||
JTextComponent c) {
|
||||
|
||||
DataFlavor refFlavor = null;
|
||||
DataFlavor stringFlavor = null;
|
||||
|
||||
for (int i = 0; i < flavors.length; i++) {
|
||||
|
||||
String mime = flavors[i].getMimeType();
|
||||
if (mime.startsWith("text/plain")) {
|
||||
return flavors[i];
|
||||
}
|
||||
else if (refFlavor == null &&
|
||||
mime.startsWith("application/x-java-jvm-local-objectref") &&
|
||||
flavors[i].getRepresentationClass() == String.class) {
|
||||
refFlavor = flavors[i];
|
||||
}
|
||||
else if (stringFlavor==null &&
|
||||
flavors[i].equals(DataFlavor.stringFlavor)) {
|
||||
stringFlavor = flavors[i];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (refFlavor != null) {
|
||||
return refFlavor;
|
||||
}
|
||||
else if (stringFlavor != null) {
|
||||
return stringFlavor;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Import the given stream data into the text component.
|
||||
*/
|
||||
protected void handleReaderImport(Reader in, JTextComponent c)
|
||||
throws IOException {
|
||||
|
||||
char[] buff = new char[1024];
|
||||
int nch;
|
||||
boolean lastWasCR = false;
|
||||
int last;
|
||||
StringBuilder sbuff = null;
|
||||
|
||||
// Read in a block at a time, mapping \r\n to \n, as well as single
|
||||
// \r to \n.
|
||||
while ((nch = in.read(buff, 0, buff.length)) != -1) {
|
||||
|
||||
if (sbuff == null) {
|
||||
sbuff = new StringBuilder(nch);
|
||||
}
|
||||
last = 0;
|
||||
|
||||
for (int counter = 0; counter < nch; counter++) {
|
||||
|
||||
switch (buff[counter]) {
|
||||
case '\r':
|
||||
if (lastWasCR) {
|
||||
if (counter == 0) {
|
||||
sbuff.append('\n');
|
||||
}
|
||||
else {
|
||||
buff[counter - 1] = '\n';
|
||||
}
|
||||
}
|
||||
else {
|
||||
lastWasCR = true;
|
||||
}
|
||||
break;
|
||||
case '\n':
|
||||
if (lastWasCR) {
|
||||
if (counter > (last + 1)) {
|
||||
sbuff.append(buff, last, counter - last - 1);
|
||||
}
|
||||
// else nothing to do, can skip \r, next write will
|
||||
// write \n
|
||||
lastWasCR = false;
|
||||
last = counter;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (lastWasCR) {
|
||||
if (counter == 0) {
|
||||
sbuff.append('\n');
|
||||
}
|
||||
else {
|
||||
buff[counter - 1] = '\n';
|
||||
}
|
||||
lastWasCR = false;
|
||||
}
|
||||
break;
|
||||
|
||||
} // End fo switch (buff[counter]).
|
||||
|
||||
} // End of for (int counter = 0; counter < nch; counter++).
|
||||
|
||||
if (last < nch) {
|
||||
if (lastWasCR) {
|
||||
if (last < (nch - 1)) {
|
||||
sbuff.append(buff, last, nch - last - 1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
sbuff.append(buff, last, nch - last);
|
||||
}
|
||||
}
|
||||
|
||||
} // End of while ((nch = in.read(buff, 0, buff.length)) != -1).
|
||||
|
||||
if (withinSameComponent) {
|
||||
((RTextArea)c).beginAtomicEdit();
|
||||
}
|
||||
|
||||
if (lastWasCR) {
|
||||
sbuff.append('\n');
|
||||
}
|
||||
c.replaceSelection(sbuff != null ? sbuff.toString() : "");
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This is the type of transfer actions supported by the source. Some
|
||||
* models are not mutable, so a transfer operation of COPY only should
|
||||
* be advertised in that case.
|
||||
*
|
||||
* @param c The component holding the data to be transfered. This
|
||||
* argument is provided to enable sharing of TransferHandlers by
|
||||
* multiple components.
|
||||
* @return If the text component is editable, COPY_OR_MOVE is returned,
|
||||
* otherwise just COPY is allowed.
|
||||
*/
|
||||
@Override
|
||||
public int getSourceActions(JComponent c) {
|
||||
if (((JTextComponent)c).isEditable()) {
|
||||
return COPY_OR_MOVE;
|
||||
}
|
||||
else {
|
||||
return COPY;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a Transferable to use as the source for a data transfer.
|
||||
*
|
||||
* @param comp The component holding the data to be transfered. This
|
||||
* argument is provided to enable sharing of TransferHandlers by
|
||||
* multiple components.
|
||||
* @return The representation of the data to be transfered.
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
protected Transferable createTransferable(JComponent comp) {
|
||||
exportComp = (JTextComponent)comp;
|
||||
shouldRemove = true;
|
||||
p0 = exportComp.getSelectionStart();
|
||||
p1 = exportComp.getSelectionEnd();
|
||||
return (p0 != p1) ? (new TextTransferable(exportComp, p0, p1)) : null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method is called after data has been exported. This method should
|
||||
* remove the data that was transfered if the action was MOVE.
|
||||
*
|
||||
* @param source The component that was the source of the data.
|
||||
* @param data The data that was transferred or possibly null
|
||||
* if the action is <code>NONE</code>.
|
||||
* @param action The actual action that was performed.
|
||||
*/
|
||||
@Override
|
||||
protected void exportDone(JComponent source, Transferable data, int action) {
|
||||
// only remove the text if shouldRemove has not been set to
|
||||
// false by importData and only if the action is a move
|
||||
if (shouldRemove && action == MOVE) {
|
||||
TextTransferable t = (TextTransferable)data;
|
||||
t.removeText();
|
||||
if (withinSameComponent) {
|
||||
((RTextArea)source).endAtomicEdit();
|
||||
withinSameComponent = false;
|
||||
}
|
||||
}
|
||||
exportComp = null;
|
||||
if (data instanceof TextTransferable) {
|
||||
ClipboardHistory.get().add(((TextTransferable)data).getPlainData());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method causes a transfer to a component from a clipboard or a
|
||||
* DND drop operation. The Transferable represents the data to be
|
||||
* imported into the component.
|
||||
*
|
||||
* @param comp The component to receive the transfer. This
|
||||
* argument is provided to enable sharing of TransferHandlers by
|
||||
* multiple components.
|
||||
* @param t The data to import
|
||||
* @return <code>true</code> iff the data was inserted into the component.
|
||||
*/
|
||||
@Override
|
||||
public boolean importData(JComponent comp, Transferable t) {
|
||||
|
||||
JTextComponent c = (JTextComponent)comp;
|
||||
withinSameComponent = c==exportComp;
|
||||
|
||||
// if we are importing to the same component that we exported from
|
||||
// then don't actually do anything if the drop location is inside
|
||||
// the drag location and set shouldRemove to false so that exportDone
|
||||
// knows not to remove any data
|
||||
if (withinSameComponent && c.getCaretPosition()>=p0 && c.getCaretPosition()<=p1) {
|
||||
shouldRemove = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean imported = false;
|
||||
DataFlavor importFlavor = getImportFlavor(t.getTransferDataFlavors(), c);
|
||||
if (importFlavor != null) {
|
||||
try {
|
||||
InputContext ic = c.getInputContext();
|
||||
if (ic != null) {
|
||||
ic.endComposition();
|
||||
}
|
||||
Reader r = importFlavor.getReaderForText(t);
|
||||
handleReaderImport(r, c);
|
||||
imported = true;
|
||||
} catch (UnsupportedFlavorException ufe) {
|
||||
ufe.printStackTrace();
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
return imported;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method indicates if a component would accept an import of the
|
||||
* given set of data flavors prior to actually attempting to import it.
|
||||
*
|
||||
* @param comp The component to receive the transfer. This argument is
|
||||
* provided to enable sharing of TransferHandlers by multiple
|
||||
* components.
|
||||
* @param flavors The data formats available.
|
||||
* @return <code>true</code> iff the data can be inserted.
|
||||
*/
|
||||
@Override
|
||||
public boolean canImport(JComponent comp, DataFlavor[] flavors) {
|
||||
JTextComponent c = (JTextComponent)comp;
|
||||
if (!(c.isEditable() && c.isEnabled())) {
|
||||
return false;
|
||||
}
|
||||
return (getImportFlavor(flavors, c) != null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A possible implementation of the Transferable interface for RTextAreas.
|
||||
*/
|
||||
static class TextTransferable implements Transferable {
|
||||
|
||||
private Position p0;
|
||||
private Position p1;
|
||||
private JTextComponent c;
|
||||
|
||||
protected String plainData;
|
||||
|
||||
private static DataFlavor[] stringFlavors;
|
||||
private static DataFlavor[] plainFlavors;
|
||||
|
||||
TextTransferable(JTextComponent c, int start, int end) {
|
||||
this.c = c;
|
||||
Document doc = c.getDocument();
|
||||
try {
|
||||
p0 = doc.createPosition(start);
|
||||
p1 = doc.createPosition(end);
|
||||
plainData = c.getSelectedText();
|
||||
} catch (BadLocationException ble) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the data in a text/plain format.
|
||||
*/
|
||||
protected String getPlainData() {
|
||||
return plainData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an object which represents the data to be transferred. The class
|
||||
* of the object returned is defined by the representation class of the flavor.
|
||||
*
|
||||
* @param flavor the requested flavor for the data
|
||||
* @see DataFlavor#getRepresentationClass
|
||||
* @exception IOException if the data is no longer available
|
||||
* in the requested flavor.
|
||||
* @exception UnsupportedFlavorException if the requested data flavor is
|
||||
* not supported.
|
||||
*/
|
||||
@Override
|
||||
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
|
||||
if (isPlainFlavor(flavor)) {
|
||||
String data = getPlainData();
|
||||
data = (data == null) ? "" : data;
|
||||
if (String.class.equals(flavor.getRepresentationClass())) {
|
||||
return data;
|
||||
} else if (Reader.class.equals(flavor.getRepresentationClass())) {
|
||||
return new StringReader(data);
|
||||
} else if (InputStream.class.equals(flavor.getRepresentationClass())) {
|
||||
return new StringBufferInputStream(data);
|
||||
}
|
||||
// fall through to unsupported
|
||||
} else if (isStringFlavor(flavor)) {
|
||||
String data = getPlainData();
|
||||
data = (data == null) ? "" : data;
|
||||
return data;
|
||||
}
|
||||
throw new UnsupportedFlavorException(flavor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of DataFlavor objects indicating the flavors the data
|
||||
* can be provided in. The array should be ordered according to preference
|
||||
* for providing the data (from most richly descriptive to least descriptive).
|
||||
*
|
||||
* @return an array of data flavors in which this data can be transferred
|
||||
*/
|
||||
@Override
|
||||
public DataFlavor[] getTransferDataFlavors() {
|
||||
|
||||
int plainCount = (isPlainSupported()) ? plainFlavors.length: 0;
|
||||
int stringCount = (isPlainSupported()) ? stringFlavors.length : 0;
|
||||
int totalCount = plainCount + stringCount;
|
||||
DataFlavor[] flavors = new DataFlavor[totalCount];
|
||||
|
||||
// fill in the array
|
||||
int pos = 0;
|
||||
if (plainCount > 0) {
|
||||
System.arraycopy(plainFlavors, 0, flavors, pos, plainCount);
|
||||
pos += plainCount;
|
||||
}
|
||||
if (stringCount > 0) {
|
||||
System.arraycopy(stringFlavors, 0, flavors, pos, stringCount);
|
||||
//pos += stringCount;
|
||||
}
|
||||
|
||||
return flavors;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the specified data flavor is supported for
|
||||
* this object.
|
||||
* @param flavor the requested flavor for the data
|
||||
* @return boolean indicating whether or not the data flavor is supported
|
||||
*/
|
||||
@Override
|
||||
public boolean isDataFlavorSupported(DataFlavor flavor) {
|
||||
DataFlavor[] flavors = getTransferDataFlavors();
|
||||
for (int i = 0; i < flavors.length; i++) {
|
||||
if (flavors[i].equals(flavor)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the specified data flavor is an plain flavor that
|
||||
* is supported.
|
||||
* @param flavor the requested flavor for the data
|
||||
* @return boolean indicating whether or not the data flavor is supported
|
||||
*/
|
||||
protected boolean isPlainFlavor(DataFlavor flavor) {
|
||||
DataFlavor[] flavors = plainFlavors;
|
||||
for (int i = 0; i < flavors.length; i++) {
|
||||
if (flavors[i].equals(flavor)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should the plain text flavors be offered? If so, the method
|
||||
* getPlainData should be implemented to provide something reasonable.
|
||||
*/
|
||||
protected boolean isPlainSupported() {
|
||||
return plainData != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the specified data flavor is a String flavor that
|
||||
* is supported.
|
||||
* @param flavor the requested flavor for the data
|
||||
* @return boolean indicating whether or not the data flavor is supported
|
||||
*/
|
||||
protected boolean isStringFlavor(DataFlavor flavor) {
|
||||
DataFlavor[] flavors = stringFlavors;
|
||||
for (int i = 0; i < flavors.length; i++) {
|
||||
if (flavors[i].equals(flavor)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void removeText() {
|
||||
if ((p0 != null) && (p1 != null) && (p0.getOffset() != p1.getOffset())) {
|
||||
try {
|
||||
Document doc = c.getDocument();
|
||||
doc.remove(p0.getOffset(), p1.getOffset() - p0.getOffset());
|
||||
} catch (BadLocationException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initialization of supported flavors.
|
||||
static {
|
||||
try {
|
||||
|
||||
plainFlavors = new DataFlavor[3];
|
||||
plainFlavors[0] = new DataFlavor("text/plain;class=java.lang.String");
|
||||
plainFlavors[1] = new DataFlavor("text/plain;class=java.io.Reader");
|
||||
plainFlavors[2] = new DataFlavor("text/plain;charset=unicode;class=java.io.InputStream");
|
||||
|
||||
stringFlavors = new DataFlavor[2];
|
||||
stringFlavors[0] = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType+";class=java.lang.String");
|
||||
stringFlavors[1] = DataFlavor.stringFlavor;
|
||||
|
||||
} catch (ClassNotFoundException cle) {
|
||||
System.err.println("Error initializing org.fife.ui.RTATextTransferHandler");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user