Archived

This topic is now archived and is closed to further replies.

pirate_dau

[java] Pasting in a JTextComponent

Recommended Posts

I'm working on a sort of WYSIWYG html editor (much like a castrated version of dreamweaver), but I've run into a problem pasting. Oh, btw, please don't post on the questionable utility of such a project -- I've heard all that before, and agree with much of it. My problem is that in order to paste HTML-formatted text from other programs (such as MS Word), I must get the data from the clipboard, process it (remove unnecessary tags, such as MS's wonderful tags.. wtf are those anyway? heh), and THEN I need to paste it. The only way that I've found I've been able to paste is by.. well, let me explain it in steps (that'll probably be clearer).
  1. Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null)  
    (get original data off of the clipboard)
  2. if a text/html DataFlavor is supported, get that and process the data
  3. Place processed data into clipboard
  4. Call the JTextComponent paste() function
  5. Replace clipboard contents with the ORIGINAL data again
This process is quite slow, as the data in the clipboard can be rather large. It would obviously be advantageous to only touch the clipboard once -- to get the original data. However, my attempts at using JTextComponent's replaceSelection(String) function have failed, since it likes to convert the less than and greater than signs into their HTML code equivalents (you know those wacky ampersand codes..). Any thoughts on how to accomplish this? There's got to be a better way... EDIT: Formatting -pirate_dau Edited by - pirate_dau on March 18, 2002 1:45:03 PM

Share this post


Link to post
Share on other sites
Hey, it''s taken me a long time to figure out (I was looking at this among other things for about a week now), but I figured it out. In the JDK1.4 they changed how pasting is handled. There is now a TransferHandler (javax.swing.TransferHandler) which contains the default paste operation.

Which means -- all I have to do is make my own class that extends TransferHandler, modify the paste operation, then setTransferHandler on my JTextPane (whew!).

-pirate_dau

Share this post


Link to post
Share on other sites
You know you would THINK what I described (more or less) would work, but for some reason when I try to modify the importData function in TransferHandler, I don''t quite get the results I would expect. For example I have been unable to get a Transferable object (that''s one of the arguments passed to importData) for which isDataFlavorSupported(new DataFlavor("text/html; class=java.lang.String") returns true.

Now I have an inkling it may have to do with other code that I''ve tinkered with, so tommorrow I''ll reduce it down to the most basic level I can and see if it doesn''t work there.

But also disturbing, is that I found when I tried to call super.importData(comp, t) (where ''comp'' and ''t'' were the arguments passed to MY TransferHandler''s importData), it would always fail. Hmm, I''m not quite sure what''s going on there. Maybe when I get it down to a really basic level it will become apparent, though.

I hope you don''t mind my posting about my ongoing process to solve this problem. Hopefully either somebody can chime in and help me with it, or if not, then somebody else can learn from it.

-pirate_dau

Share this post


Link to post
Share on other sites
SUCCESS!!!

Well, I figured it out. I was relaxing, taking a break with a friend of mine, and explaining my problem to him. But then it suddenly hit me out of nowhere the solution. All I had to do was make a really simple Transferable object, and then in my modified Paste Action, call on
HTMLEditor.getTransferHandler().importData(HTMLEditor, new HtmlTransfer(myModifiedClipboardData));  

If you're wondering what the HtmlTransfer object looks like, it's really very simple -- check it...

    
package cdt.editor ;

import java.util.Arrays ;
import java.awt.datatransfer.* ;


/**
* This class is used to call <code>importData(JComponent, Transferable)</code> with modified HTML.
* The only reason I have it is so that I can get pasting to work correctly with MS Word.
*
* @version 1.0
* @author Brad Schaefer (<A HREF="mailto:EDITED OUT">EDITED OUT</A>)
* @see cdt.editor.EditorActions#paste
*/
public class HtmlTransfer implements Transferable {

/** the html Data we are transfering. */
private String html ;

private static DataFlavor HtmlFlavor = (DataFlavor)null;

/** The transferable DataFlavors of this object */
private static DataFlavor[] flavors = { (DataFlavor)null };

/**
* Creates an HtmlTransfer object.
*
* @param html Html to store.
*/
public HtmlTransfer(String html) {
this.html = html;
if(null == HtmlFlavor) {
try {
this.HtmlFlavor = new DataFlavor("text/html; class=java.lang.String");
} catch (Exception e) {
e.printStackTrace();
this.HtmlFlavor = DataFlavor.stringFlavor;
}
this.flavors[0] = HtmlFlavor;
}
}

/**
* Gets the Html that is stored.
*
* @param flavor Requested DataFlavor of the transfer data.
* @return Html stored in this object.
*/
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException {
if(flavor == HtmlFlavor) {
return html;
} else {
throw new UnsupportedFlavorException(flavor);
}
}

/**
* Gets an array of supported DataFlavors.
*
* @return array of supported DataFlavors.
*/
public DataFlavor[] getTransferDataFlavors() {
return flavors;
}

/**
* Gets where a DataFlavor is supported by this Transferable object.
*
* @param flavor DataFlavor to check for support.
* @return Whether the DataFlavor is supported.
*/

public boolean isDataFlavorSupported(DataFlavor flavor) {
return Arrays.asList(flavors).contains(flavor);
}
}


It's funny how a little caffine and a little bit of explaining the problem to somebody else can solve your problems.

EDIT: Yea, I wish GameDev's source tag had an attribute to set the language to Java or something... so sorry fer the bad-looking source box, but what can I do?

-pirate_dau

[edited by - pirate_dau on March 20, 2002 4:04:20 PM]

Share this post


Link to post
Share on other sites