Reputation: 425
Good day to everyone!
I'm working on text editor with styles support. And in the application there will be several text editors. I think it will be a good idea to allow drag styled text from one JTextPane to another. Looks like JTextPane supports dragging of text with styles within itself. You can launch the code below to check it. But when I drag styled text to another JTextPane, the text being inserted is PLAIN. :( I watched through source codes and found one interesting class - TextTransferHandler. After debugging it became obvious this TextTransferHandler handles drag and drop. As I see in its code it supports dragging of styled text by converting the text to RTF or HTML. I tried this:
_tp.setEditorKit(new RTFEditorKit());
but without success.
Am I'm missing something?
The code:
package apps.editor;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.ResourceBundle;
import javax.swing.Action;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JTextPane;
import javax.swing.JToolBar;
import javax.swing.KeyStroke;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import javax.swing.text.DefaultEditorKit;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.JTextComponent;
import javax.swing.text.Keymap;
import javax.swing.text.rtf.RTFEditorKit;
class EditorUtil2 {
Action[] _actions;
HashMap<String, Action> _actionHashMap = new HashMap<String, Action>();
ResourceBundle _resourceBundle = BundleFactory.getBundle();
JTextPane _initTextPane;
Keymap _keymap;
JPopupMenu _popupMenu;
ArrayList<JTextPane> _editors = new ArrayList<JTextPane>();
public EditorUtil2() {
_initTextPane = new JTextPane();
hashDefaultActions();
makeActionsPretty();
makeKeymap();
createPopupMenu();
}
private String getProperty(String key) {
return _resourceBundle.getString(key);
}
private void hashDefaultActions() {
_actions = _initTextPane.getActions();
String name = null;
for (int i=0; i<_actions.length; i++) {
name = (String)_actions[i].getValue( Action.NAME );
_actionHashMap.put( name, _actions[i] );
}
}
private Action getHashedAction(String name) {
return (Action)_actionHashMap.get( name );
}
private void makeActionsPretty() {
Action a;
a = getHashedAction( DefaultEditorKit.cutAction );
a.putValue( Action.SMALL_ICON, loadImage( getProperty("Toolbar.Icons.cut") ) );
a.putValue( Action.NAME, getProperty("Toolbar.cut") );
a = getHashedAction( DefaultEditorKit.copyAction );
a.putValue( Action.SMALL_ICON, loadImage( getProperty("Toolbar.Icons.copy") ) );
a.putValue( Action.NAME, getProperty("Toolbar.copy") );
a = getHashedAction( DefaultEditorKit.pasteAction );
a.putValue( Action.SMALL_ICON, loadImage( getProperty("Toolbar.Icons.paste") ) );
a.putValue( Action.NAME, getProperty("Toolbar.paste") );
a = getHashedAction("font-bold");
a.putValue( Action.SMALL_ICON, loadImage( getProperty("Toolbar.Icons.bold") ) );
a.putValue( Action.NAME, getProperty("Toolbar.bold") );
a = getHashedAction("font-italic");
a.putValue( Action.SMALL_ICON, loadImage( getProperty("Toolbar.Icons.italic") ) );
a.putValue( Action.NAME, getProperty("Toolbar.italic") );
a = getHashedAction("font-underline");
a.putValue( Action.SMALL_ICON, loadImage( getProperty("Toolbar.Icons.underline") ) );
a.putValue( Action.NAME, getProperty("Toolbar.underline") );
}
private void makeKeymap() {
_keymap = JTextComponent.addKeymap( "NewKeymap", _initTextPane.getKeymap() );
//KeyStroke next = KeyStroke.getKeyStroke( KeyEvent.VK_RIGHT, InputEvent.CTRL_MASK, false);
//KeyStroke prev = KeyStroke.getKeyStroke( KeyEvent.VK_LEFT, InputEvent.CTRL_MASK, false);
//KeyStroke selectNext = KeyStroke.getKeyStroke( KeyEvent.VK_RIGHT, InputEvent.CTRL_MASK | InputEvent.SHIFT_MASK, false);
//KeyStroke selectPrev = KeyStroke.getKeyStroke( KeyEvent.VK_LEFT, InputEvent.CTRL_MASK | InputEvent.SHIFT_MASK, false);
KeyStroke cut = KeyStroke.getKeyStroke( KeyEvent.VK_X, InputEvent.CTRL_MASK, false);
KeyStroke copy = KeyStroke.getKeyStroke( KeyEvent.VK_C, InputEvent.CTRL_MASK, false);
KeyStroke paste = KeyStroke.getKeyStroke( KeyEvent.VK_V, InputEvent.CTRL_MASK, false);
KeyStroke bold = KeyStroke.getKeyStroke( KeyEvent.VK_B, InputEvent.CTRL_MASK, false);
KeyStroke italic = KeyStroke.getKeyStroke( KeyEvent.VK_I, InputEvent.CTRL_MASK, false);
KeyStroke underline = KeyStroke.getKeyStroke( KeyEvent.VK_U, InputEvent.CTRL_MASK, false);
//_keymap.addActionForKeyStroke( next, getHashedAction( DefaultEditorKit.nextWordAction ) );
//_keymap.addActionForKeyStroke( prev, getHashedAction( DefaultEditorKit.previousWordAction ) );
//_keymap.addActionForKeyStroke( selectNext, getHashedAction( DefaultEditorKit.selectionNextWordAction ) );
//_keymap.addActionForKeyStroke( selectPrev, getHashedAction( DefaultEditorKit.selectionPreviousWordAction ) );
_keymap.addActionForKeyStroke( cut, getHashedAction( DefaultEditorKit.cutAction) );
_keymap.addActionForKeyStroke( copy, getHashedAction( DefaultEditorKit.copyAction ) );
_keymap.addActionForKeyStroke( paste, getHashedAction( DefaultEditorKit.pasteAction ) );
_keymap.addActionForKeyStroke( bold, getHashedAction( "font-bold" ) );
_keymap.addActionForKeyStroke( italic, getHashedAction( "font-italic" ) );
_keymap.addActionForKeyStroke( underline, getHashedAction( "font-underline" ) );
}
private ImageIcon loadImage(String path) {
URL imageURL = this.getClass().getResource( path );
return new ImageIcon( imageURL );
}
private void createPopupMenu() {
_popupMenu = new JPopupMenu();
ArrayList<Action> actions = new ArrayList<Action>();
actions.add( getHashedAction( DefaultEditorKit.cutAction ) );
actions.add( getHashedAction( DefaultEditorKit.copyAction ) );
actions.add( getHashedAction( DefaultEditorKit.pasteAction ) );
JMenuItem mi = null;
for (Action a : actions) {
mi = new JMenuItem();
mi.setAction(a);
mi.setAccelerator(_keymap.getKeyStrokesForAction( a )[0] );
_popupMenu.add(mi);
}
_popupMenu.addPopupMenuListener(new PopupMenuListener() {
@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
System.out.println("will be visible");
}
@Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
System.out.println("will be invisible");
System.out.println("stop freeze");
JTextPane tp = (JTextPane)_popupMenu.getInvoker();
tp.getCaret().setBlinkRate(500);
tp.getCaret().setVisible(false);
//_popupOpened = false;
tp.repaint();
//tp.requestFocus();
}
@Override
public void popupMenuCanceled(PopupMenuEvent e) {
System.out.println("menu canceled");
}
} );
_popupMenu.addComponentListener( new ComponentAdapter() {
@Override
public void componentShown(ComponentEvent e) {
System.out.println("menu shown");
}
@Override
public void componentHidden(ComponentEvent e) {
}
});
}
boolean _popupOpened = false;
public JTextPane createTextEditor() {
final JTextPane tp = new JTextPane();
_editors.add( tp );
tp.setKeymap(_keymap);
tp.addFocusListener(new FocusAdapter() {
@Override
public void focusLost(FocusEvent e) {
if (_popupMenu.isShowing() && _popupMenu.getInvoker() == tp) {
JTextPane tp = (JTextPane)_popupMenu.getInvoker();
tp.getCaret().setBlinkRate(0);
tp.getCaret().setVisible(true);
tp.repaint();
}
}
@Override
public void focusGained(FocusEvent e) {
System.out.println("focus gained");
for ( JTextPane t : _editors )
if ( t != tp )
t.setCaretPosition( t.getCaretPosition() );
}
});
tp.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(final MouseEvent e) {
System.out.println("mouse pressed");
tp.requestFocus();
if ( tp.getSelectionStart() == tp.getSelectionEnd() )
tp.setCaretPosition( tp.viewToModel( e.getPoint() ) );
if ( e.isPopupTrigger() ) {
_popupMenu.show( e.getComponent(), e.getX(), e.getY() );
}
}
@Override
public void mouseReleased(MouseEvent e) {
System.out.println("mouse released");
// tp.requestFocus();
// if ( e.isPopupTrigger() ) {
// _popupMenu.show( e.getComponent(), e.getX(), e.getY() );
// }
}
});
return tp;
}
public ArrayList<Action> getActionsForToolBar() {
ArrayList<Action> actions = new ArrayList<Action>();
actions.add( getHashedAction( DefaultEditorKit.cutAction ) );
actions.add( getHashedAction( DefaultEditorKit.copyAction ) );
actions.add( getHashedAction( DefaultEditorKit.pasteAction ) );
actions.add( getHashedAction("font-bold") );
actions.add( getHashedAction("font-italic") );
actions.add( getHashedAction("font-underline") );
return actions;
}
public ArrayList<JMenuItem> getMenuItems() {
ArrayList<JMenuItem> items = new ArrayList<JMenuItem>();
ArrayList<Action> actions = new ArrayList<Action>();
actions.add( getHashedAction( DefaultEditorKit.cutAction ) );
actions.add( getHashedAction( DefaultEditorKit.copyAction ) );
actions.add( getHashedAction( DefaultEditorKit.pasteAction ) );
JMenuItem mi = null;
for (Action a : actions) {
mi = new JMenuItem();
mi.setAction(a);
mi.setAccelerator(_keymap.getKeyStrokesForAction( a )[0] );
items.add(mi);
}
return items;
}
}
public class TextEditorFrame2 extends LFrame {
EditorUtil _editorUtil = new EditorUtil();
JTextPane _tp;
JTextPane _tp2;
HashMap<String, Action> actionHashMap = new HashMap<String, Action>();
public TextEditorFrame2() {
setTitle("Editor");
setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
_tp = _editorUtil.createTextEditor();
_tp2 = _editorUtil.createTextEditor();
add( createToolBar(), BorderLayout.NORTH );
add( _tp, BorderLayout.CENTER );
add( _tp2, BorderLayout.SOUTH );
setJMenuBar( createMenuBar() );
_tp.setDragEnabled(true);
_tp2.setDragEnabled(true);
//_tp.setContentType("text/rtf");
_tp.setEditorKit(new RTFEditorKit());
_tp2.setEditorKit(new RTFEditorKit());
//_tp2.setContentType("text/rtf");
System.out.println(_tp.getEditorKit());
pack();
setVisible(true);
setLocation(200, 300);
}
private JToolBar createToolBar() {
JToolBar tb = new JToolBar();
ArrayList<Action> actions = _editorUtil.getActionsForToolBar();
for (Action a : actions)
tb.add( a );
JButton button = new JButton("dump");
tb.add(button);
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
DefaultStyledDocument doc = (DefaultStyledDocument)_tp.getStyledDocument();
doc.dump(System.out);
}
});
return tb;
}
private JMenuBar createMenuBar() {
JMenuBar mb = new JMenuBar();
JMenu edit = new JMenu("Edit");
mb.add(edit);
ArrayList<JMenuItem> items = _editorUtil.getMenuItems();
for (JMenuItem i : items)
edit.add( i );
return mb;
}
public static void main(String[] args) {
new TextEditorFrame();
}
}
Upvotes: 2
Views: 745
Reputation: 57421
You can try the kit http://java-sl.com/advanced_rtf_editor_kit.html
It supports much more RTF features than default one. Also it supports copy/paste styled content. Guess it will work ok with D&D as well.
Upvotes: 2