Thunderforge
Thunderforge

Reputation: 20595

Right Click Menu Items for System Clipboard Operations

I've discovered that when running a Java program in Mac OS X, text field objects (e.g. JField) support cut, copy, and paste operations using the system clipboard if you use the key commands without you having to do an extra coding. For instance, I can create a JField, type in some text, select it, and then use "Command-C" to copy it, then paste it in another application. The same works for pasting text copied from other applications.

I really like that Java does this automatically, but I notice that the Edit menu doesn't appear automatically with the cut, copy, and paste menu items. Is there any way to automatically add these menu items for accessing the system clipboard when text is selected? If not, what's the best way to implement them so that it behaves like any other application. At this point, I'm only interested in copy and pasting text.

Also, I know that the system clipboard is platform specific. Does this automatic system clipboard functionality for text field objects occur on other platforms?

EDIT: I was actually wanting to know about adding this to the menu bar, but there wound up being such a great answer to the next question I would have had that I decided that I'd select it as the right answer and rename the question.

Upvotes: 2

Views: 1074

Answers (3)

Ky -
Ky -

Reputation: 32153

This has worked for me:

public class MyTextField extends JTextField {
    public static final MyPopupMenu POPUP_MENU = new MyPopupMenu();

    public MyTextField() {
        this.setComponentPopupMenu(POPUP_MENU);
    }
}

Now, I just use MyTextField everywhere I would otherwise use a JTextField.

Upvotes: 0

FThompson
FThompson

Reputation: 28707

You will need to create a custom popup menu for this, which can be done utilizing MouseListener (or MouseAdapter) and a JPopupMenu. My approach would be to create a custom mouse listener which you can add to any text component.

public class ClipboardMenuHandler extends MouseAdapter {

    private final JTextComponent textComponent;

    public ClipboardMenuHandler(JTextComponent textComponent) {
        this.textComponent = textComponent;
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        if (e.isPopupTrigger()) 
            ClipboardMenu menu = new ClipboardMenu();
            menu.show(textComponent, e.getX(), e.getY());
        }
    }

    private class ClipboardMenu extends JPopupMenu {

        public ClipboardMenu() {
            // add copy/cut/paste actions; refer to Ted's answer for PasteAction
        }
    }
}

Then, you just add a ClipboardMenuHandler as a listener to your text component.

JTextField field = new JTextField();
ClipboardMenuHandler menuHandler = new ClipboardMenuHandler(field);
field.addMouseListener(menuHandler);

Upvotes: 1

Ted Hopp
Ted Hopp

Reputation: 234857

Unfortunately, Swing does not support pop-up context menus. You have to roll your own. Fortunately, this isn't too hard. Perhaps the cleanest approach is to install your own event queue, as described here. That article suggests the following implementation:

// @author Santhosh Kumar T - [email protected] 
public class MyEventQueue extends EventQueue{ 
    protected void dispatchEvent(AWTEvent event){ 
        super.dispatchEvent(event); 

        // interested only in mouseevents 
        if(!(event instanceof MouseEvent)) 
            return; 

        MouseEvent me = (MouseEvent)event; 

        // interested only in popuptriggers 
        if(!me.isPopupTrigger()) 
            return; 

        // me.getComponent(...) retunrs the heavy weight component on which event occured 
        Component comp = SwingUtilities.getDeepestComponentAt(me.getComponent(), me.getX(), me.getY()); 

        // interested only in textcomponents 
        if(!(comp instanceof JTextComponent)) 
            return; 

        // no popup shown by user code 
        if(MenuSelectionManager.defaultManager().getSelectedPath().length>0) 
            return; 

        // create popup menu and show 
        JTextComponent tc = (JTextComponent)comp; 
        JPopupMenu menu = new JPopupMenu(); 
        menu.add(new CutAction(tc)); 
        menu.add(new CopyAction(tc)); 
        menu.add(new PasteAction(tc)); 
        menu.add(new DeleteAction(tc)); 
        menu.addSeparator(); 
        menu.add(new SelectAllAction(tc)); 

        Point pt = SwingUtilities.convertPoint(me.getComponent(), me.getPoint(), tc);
        menu.show(tc, pt.x, pt.y);
    } 
}

You then use this with:

public static void main(String[] args){ 
    Toolkit.getDefaultToolkit().getSystemEventQueue().push(new MyEventQueue()); 

    .....
}

With that one line of code, you get a pop-up menu on every text component in your application.

The actions classes aren't too complicated. For instance, here's the implementation of the paste action, which shows interaction with the system clipboard:

// @author Santhosh Kumar T - [email protected] 
class PasteAction extends AbstractAction{ 
    JTextComponent comp; 

    public PasteAction(JTextComponent comp){ 
        super("Paste"); 
        this.comp = comp; 
    } 

    public void actionPerformed(ActionEvent e){ 
        comp.paste(); 
    } 

    public boolean isEnabled(){ 
        if (comp.isEditable() && comp.isEnabled()){ 
            Transferable contents = Toolkit.getDefaultToolkit().getSystemClipboard().getContents(this); 
            return contents.isDataFlavorSupported(DataFlavor.stringFlavor); 
        }else 
            return false; 
    } 
}

See the article for code for the other action implementations.

Upvotes: 2

Related Questions