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.

Bug 134643 - Subversion commit message text box needs popup menu
Summary: Subversion commit message text box needs popup menu
Status: RESOLVED FIXED
Alias: None
Product: versioncontrol
Classification: Unclassified
Component: Subversion (show other bugs)
Version: 6.x
Hardware: All All
: P3 blocker with 1 vote (vote)
Assignee: ma.schroed
URL:
Keywords: SIMPLEFIX
Depends on:
Blocks: 205646
  Show dependency tree
 
Reported: 2008-05-07 02:06 UTC by rstaff
Modified: 2011-12-02 11:58 UTC (History)
2 users (show)

See Also:
Issue Type: ENHANCEMENT
Exception Reporter:


Attachments
patch which creates a popup for the text area (16.73 KB, text/plain)
2011-10-26 17:14 UTC, ma.schroed
Details
working patch (12.20 KB, text/plain)
2011-10-27 14:01 UTC, ma.schroed
Details
patch which adds new classes (11.58 KB, text/plain)
2011-10-27 18:08 UTC, ma.schroed
Details
patch uses actions from the text component (11.29 KB, patch)
2011-11-04 10:35 UTC, ma.schroed
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description rstaff 2008-05-07 02:06:50 UTC
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.
Comment 1 Eduardo.m Costa 2008-12-01 13:01:32 UTC
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).
Comment 2 tomwheeler 2011-10-01 04:04:34 UTC
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.
Comment 3 ma.schroed 2011-10-19 19:53:59 UTC
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.
Comment 4 ma.schroed 2011-10-26 17:14:06 UTC
Created attachment 112471 [details]
patch which creates a popup for the text area
Comment 5 Ondrej Vrabec 2011-10-27 08:17:56 UTC
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
Comment 6 Michel Graciano 2011-10-27 11:28:36 UTC
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.
Comment 7 Ondrej Vrabec 2011-10-27 11:40:37 UTC
> 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 8 ma.schroed 2011-10-27 14:00:19 UTC
Comment on attachment 112471 [details]
patch which creates a popup for the text area

Thhis was a zip upload, dont use it!
Comment 9 ma.schroed 2011-10-27 14:01:47 UTC
Created attachment 112500 [details]
working patch

this patch was tested against main-silver
Comment 10 Michel Graciano 2011-10-27 14:10:08 UTC
Mario,
there is a change at cnd project in the patch too. AFAIK it is not part of this issue right?
Comment 11 ma.schroed 2011-10-27 18:04:42 UTC
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();
+            }
+        }
+        
+    }
+    
+}
Comment 12 ma.schroed 2011-10-27 18:08:45 UTC
Created attachment 112508 [details]
patch which adds new classes

changes only necessary files
Comment 13 Michel Graciano 2011-11-01 14:12:27 UTC
The patch is not ready yet. I have found issues regarding how shortcuts are displayed.
Comment 14 ma.schroed 2011-11-01 16:12:34 UTC
What does this mean?
Comment 15 Ondrej Vrabec 2011-11-02 14:56:34 UTC
[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.
Comment 16 ma.schroed 2011-11-04 10:35:54 UTC
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.
Comment 17 tomwheeler 2011-11-07 06:04:13 UTC
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)?
Comment 18 Ondrej Vrabec 2011-11-07 08:20:04 UTC
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.
Comment 19 tomwheeler 2011-11-07 14:35:47 UTC
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.
Comment 20 Ondrej Vrabec 2011-11-18 11:22:02 UTC
fix pushed to trunk: http://hg.netbeans.org/core-main/rev/984a429b4f71. You may close this as RESOLVED/FIXED
Comment 21 Michel Graciano 2011-11-18 11:26:20 UTC
I will verify this as soon as it hits the main repo.
Comment 22 Quality Engineering 2011-11-19 16:16:52 UTC
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