This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.
While coding, I often write commit messages in a text file as I go, and then I copy and paste the messages into the Subversion commit dialog. Other times I write commit messages directly in the commit dialog and need to go back and check something before committing, so I copy the text in the dialog so that I can paste it back into the dialog instead of rewriting it since the new text is not saved until after committing. When writing commit messages in the Subversion commit dialog, right clicking on the text box does not do anything. Having a popup menu with the options cut, copy, and paste would be helpful. (Delete and and select all would be nice, too.) The control-x/c/v keys work, but these commands are used frequently enough in this part of the UI to justify having them available in a popup menu.
This is more like a Swing issue: by default, there's no popup menu on textboxes (even JTextField ones). I don't rememeber if all *nices have the desired behaviour (i.e. if gnome-based and kde-based and etc-based applications popups a menu on text box widgets).
To Eduardo's comment, textfields in native GNOME / GTK applications do have popup menus with the standard cut/copy/paste items on them. It's been a while since I used KDE but I am almost certain they do too.
The place to patch is in the subversion module. There is a class 'CommitPanel' which contains the text area for the commit message. I will write a mouse listener for this text box. The Constructor of the listener will call a builder for a popup menu. The builder attaches an action listener to each menu item, which finally cuts, copies or pastes chunks of text. In my opinion the popup menu should be added for an item to select the whole text in the commit message area. There will be a getter for the popup menu in the mouse listener for unit testing. The test could check the menu items and action listener. If the patch is successful it could be applied to other commit dialogs like git or mercurial. But maybe that is behind the scope of this issue.
Created attachment 112471 [details] patch which creates a popup for the text area
Please do not attach patch as a set of modified files. Generate a regular hg patch. 1) Clone your sources 2) Modify files and do your changes 3) Run in commandline: hg diff -r . subversion > proposal.patch 4) Attach the patch file
I have a little doubt. With the diff, the locally new files are not listed at the patch. How should we proceed? I usually use NetBeans to generate the diff for uncommitted changes but I would like to know how to do this by command line. Thanks in advance.
> I have a little doubt. With the diff, the locally new files are not listed at the patch. How should we proceed? Add the file to repository at first (Mercurial -> Add from 7.1 or directly on commandline: hg add NEW_FILE)
Comment on attachment 112471 [details] patch which creates a popup for the text area Thhis was a zip upload, dont use it!
Created attachment 112500 [details] working patch this patch was tested against main-silver
Mario, there is a change at cnd project in the patch too. AFAIK it is not part of this issue right?
Comment on attachment 112500 [details] working patch diff --git a/subversion/src/org/netbeans/modules/subversion/ui/commit/Bundle.properties b/subversion/src/org/netbeans/modules/subversion/ui/commit/Bundle.properties --- a/subversion/src/org/netbeans/modules/subversion/ui/commit/Bundle.properties +++ b/subversion/src/org/netbeans/modules/subversion/ui/commit/Bundle.properties @@ -179,4 +179,10 @@ LBL_Advanced=&Advanced: LBL_CommitDialog_FilesToCommit=&Files to Commit: -LBL_ResolvingConflicts=Resolving Conflicts... \ No newline at end of file +LBL_ResolvingConflicts=Resolving Conflicts... + +#popup for commit message +CTL_MenuItem_SelectAll=Select &All (-a) +CTL_MenuItem_Cut=Cu&t (-x) +CTL_MenuItem_Copy=Cop&y (-c) +CTL_MenuItem_Paste=&Paste (-v) \ No newline at end of file diff --git a/subversion/src/org/netbeans/modules/subversion/ui/commit/CommitMessageMouseAdapter.java b/subversion/src/org/netbeans/modules/subversion/ui/commit/CommitMessageMouseAdapter.java new file mode 100644 --- /dev/null +++ b/subversion/src/org/netbeans/modules/subversion/ui/commit/CommitMessageMouseAdapter.java @@ -0,0 +1,103 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2011 Sun Microsystems, Inc. + */ +package org.netbeans.modules.subversion.ui.commit; + +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; +import javax.swing.KeyStroke; +import javax.swing.text.JTextComponent; +import org.openide.actions.CopyAction; +import org.openide.actions.CutAction; +import org.openide.actions.PasteAction; +import org.openide.util.actions.CallbackSystemAction; +import org.openide.util.actions.SystemAction; + +/** + * Mouse adapter for the commit message component. + * + * @author Mario Schroeder + */ +public class CommitMessageMouseAdapter extends MouseAdapter { + + private CommitPopupBuilder popupBuilder; + + /** + * Creates a new context popupMenu for a text component. + * @param textComponent + */ + public CommitMessageMouseAdapter() { + + popupBuilder = new CommitPopupBuilder(); + } + + @Override + public void mousePressed(MouseEvent e) { + + if (e.getModifiers() == InputEvent.BUTTON3_MASK) { + show(e.getComponent(), e.getX(), e.getY()); + } + } + + /** + * Shows the popup popupMenu if the invoker is a instance of JTextComponent. + */ + private void show(Component invoker, int x, int y) { + + //to avoid class cast exception in action listener + if (invoker instanceof JTextComponent) { + JTextComponent textComponent = (JTextComponent)invoker; + JPopupMenu popupMenu = popupBuilder.getPopup(textComponent); + popupMenu.setInvoker(invoker); + popupMenu.show(invoker, x, y); + } + } + + + +} diff --git a/subversion/src/org/netbeans/modules/subversion/ui/commit/CommitPanel.java b/subversion/src/org/netbeans/modules/subversion/ui/commit/CommitPanel.java --- a/subversion/src/org/netbeans/modules/subversion/ui/commit/CommitPanel.java +++ b/subversion/src/org/netbeans/modules/subversion/ui/commit/CommitPanel.java @@ -373,6 +373,7 @@ jScrollPane1.setViewportView(messageTextArea); messageTextArea.getAccessibleContext().setAccessibleName(getMessage("ACSN_CommitForm_Message")); // NOI18N messageTextArea.getAccessibleContext().setAccessibleDescription(getMessage("ACSD_CommitForm_Message")); // NOI18N + messageTextArea.addMouseListener(new CommitMessageMouseAdapter()); Mnemonics.setLocalizedText(filesSectionButton, getMessage("LBL_CommitDialog_FilesToCommit")); // NOI18N Mnemonics.setLocalizedText(filesLabel, getMessage("CTL_CommitForm_FilesToCommit")); // NOI18N diff --git a/subversion/src/org/netbeans/modules/subversion/ui/commit/CommitPopupBuilder.java b/subversion/src/org/netbeans/modules/subversion/ui/commit/CommitPopupBuilder.java new file mode 100644 --- /dev/null +++ b/subversion/src/org/netbeans/modules/subversion/ui/commit/CommitPopupBuilder.java @@ -0,0 +1,155 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2011 Sun Microsystems, Inc. + */ +package org.netbeans.modules.subversion.ui.commit; + +import java.awt.Toolkit; +import java.awt.datatransfer.DataFlavor; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; +import javax.swing.KeyStroke; +import javax.swing.text.JTextComponent; +import org.openide.awt.Mnemonics; +import org.openide.util.NbBundle; + +/** + * Builder for the popup menu. + * + * @author Mario Schroeder + */ +class CommitPopupBuilder { + + private JPopupMenu popupPresenter; + + private JMenuItem cutMenuItem; + + private JMenuItem copyMenuItem; + + private JMenuItem pasteMenuItem; + + private JMenuItem selectAllMenuItem; + + private PopupActionListener actionListener; + + CommitPopupBuilder() { + + build(); + } + + /** + * This method builds the popup menu. + */ + private void build() { + + actionListener = new PopupActionListener(); + + popupPresenter = new JPopupMenu(); + + cutMenuItem = createMenuItem("CTL_MenuItem_Cut"); + copyMenuItem = createMenuItem("CTL_MenuItem_Copy"); + pasteMenuItem = createMenuItem("CTL_MenuItem_Paste"); + selectAllMenuItem = createMenuItem("CTL_MenuItem_SelectAll"); + + popupPresenter.add(cutMenuItem); + popupPresenter.add(copyMenuItem); + popupPresenter.add(pasteMenuItem); + popupPresenter.addSeparator(); + popupPresenter.add(selectAllMenuItem); + + } + + JPopupMenu getPopup(JTextComponent component) { + + boolean textSelected = component.getSelectedText() != null; + cutMenuItem.setEnabled(textSelected); + copyMenuItem.setEnabled(textSelected); + + boolean hasClipboardText = Toolkit.getDefaultToolkit().getSystemClipboard() + .isDataFlavorAvailable(DataFlavor.stringFlavor); + pasteMenuItem.setEnabled(hasClipboardText); + + return popupPresenter; + } + + /** + * Creates a new menu item. + * @param msgKey key for the message within resource bundle. + * @param key key for the accelerator + * @return a new menu item + */ + private JMenuItem createMenuItem(String msgKey) { + + JMenuItem item = new JMenuItem(); + String msg = NbBundle.getMessage(getClass(), msgKey); + Mnemonics.setLocalizedText(item, msg); + item.addActionListener(actionListener); + return item; + } + + /** + * Action listener for menu items. + */ + private class PopupActionListener implements ActionListener { + + @Override + public void actionPerformed(ActionEvent evt) { + Object source = evt.getSource(); + JTextComponent textComponent = (JTextComponent) popupPresenter.getInvoker(); + if (source == cutMenuItem) { + textComponent.cut(); + } + else if (source == copyMenuItem) { + textComponent.copy(); + } + else if (source == pasteMenuItem) { + textComponent.paste(); + } + else if (source == selectAllMenuItem) { + textComponent.selectAll(); + } + } + + } + +}
Created attachment 112508 [details] patch which adds new classes changes only necessary files
The patch is not ready yet. I have found issues regarding how shortcuts are displayed.
What does this mean?
[OV1] - shortcuts should not be hard-coded into a menu item, should be set via MenuItem.setAccelerator(KeyStroke) probably. That's what Michel meant in his last comment i guess [OV2] - JTextComponent has it's own cut/copy/paste/selectAll actions implementations. Can't they be accessed, obtained from the component's ActionMap (ActionMap.get(DefaultEditorKit.selectAllAction) maybe) and used instead of your own implentation? [OV3] - you should probably add shortcuts to the actions into the component's input map manually. I am not sure, but isn't the default shortcut for the copy action on Mac META+C instead of Ctrl+C? The shortcut displayed next to the action in the popup menu should correspond to the real shortcut under which the action is registered in JTextComponent.getInputMap() IMO.
Created attachment 112823 [details] patch uses actions from the text component Michel meant that the shortcuts are shown wrong. This patch reuses the actions from the text component. The meta key for the shortcuts are are provided by the toolkit: Toolkit.getDefaultToolkit().getMenuShortcutKeyMask() This should return the correct key on the underlying OS. However it should be verified on MacOS.
I have applied the patch locally, then built and tested on Linux (Ubuntu). I then tried this version on my Mac (running OS X 10.6) and it worked fine. The shortcuts on the Mac are Copy=Command-C, Cut=Command-X, Paste=Command-V and Select All=Command A, just as you'd expect. Ondrej, do you want to push the patch or shall I (I have push rights to core-main)?
I will apply and push the patch but when the 7.1 release is branched and we are once again out of the stabilization period. We cannot push any RFE fixed at this time of the release cycle.
Sounds good. Mario: A few days after Ondrej pushes the patch, you will get an e-mail from IssueZilla telling you that the change has been integrated into a nightly build. A day or two later, you should download the most recent nightly build and verify that your enhancement is included, then mark the issue VERIFIED. At that point, I will add you to the list of First Patch graduates and also add your name to the CREDITS.html file that's distributed with NetBeans. If I don't do that within a few days of you marking the issue verified, please e-mail me and remind me. Thanks for your contribution to NetBeans.
fix pushed to trunk: http://hg.netbeans.org/core-main/rev/984a429b4f71. You may close this as RESOLVED/FIXED
I will verify this as soon as it hits the main repo.
Integrated into 'main-golden' Changeset: http://hg.netbeans.org/main-golden/rev/984a429b4f71 User: ma.schroed@netbeans.org Log: Issue #134643 - Subversion commit message text box needs popup menu