Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I finally had a chance to further pursue this over the holidays. And I found a kludge of a solution. Note that this is dynamically changing the Java classes used by the Matlab GUI in runtime; it is completely unsupported and is likely to be very fragile. It works on my version of Matlab (r2011a) on OS X Lion.</p> <p>Here's what I've learned about how Swing/Matlab process keypress events:</p> <ol> <li>A keystroke is pressed.</li> <li>The active text component's <code>inputMap</code> is searched to see if there's a binding for that keystroke. <ul> <li>If there is an action bound to that keystroke, dispatch that action's <code>actionPerformed</code> method</li> <li>If there is a string associated with that keystroke, find the action from the text component's <code>actionMap</code>, and then dispatch that action's <code>actionPerformed</code> method</li> </ul></li> <li><em>No matter what</em>, as a final step, dispatch the action found within the text component's <code>Keymap.getDefaultAction()</code>. Here's where the problem lies.</li> </ol> <p>This solution overrides the Keymap's default action with a wrapper that simply checks to see if any modifier keys were pressed. If they were, the action is silently ignored.</p> <hr> <p><strong>Step 1: Create a custom TextAction in Java to ignore modifier keys</strong></p> <pre><code>import javax.swing.text.TextAction; import javax.swing.Action; import java.awt.event.ActionEvent; public class IgnoreModifiedKeystrokesAction extends TextAction { private static final int ignoredModifiersMask = ActionEvent.CTRL_MASK | ActionEvent.ALT_MASK; private Action original; public IgnoreModifiedKeystrokesAction(Action act) { super((String)act.getValue("Name")); original = act; } public void actionPerformed(ActionEvent e) { if ((e.getModifiers() &amp; ignoredModifiersMask) == 0) { /* Only dispatch the original action if no modifiers were used */ original.actionPerformed(e); } } public Action getOriginalAction() { return original; } } </code></pre> <p>Compile to a <code>.jar</code>:</p> <pre><code>javac IgnoreModifiedKeystrokesAction.java &amp;&amp; jar cvf IgnoreModifiedKeystrokesAction.jar IgnoreModifiedKeystrokesAction.class </code></pre> <hr> <p><strong>Step 2: Override MATLAB's default Keymap handler in both the command window and editor (from within MATLAB)</strong></p> <p>The hardest part here is getting the java handles to the command window and editor. It is dependent upon the layout and classnames of the individual editor panes. This may change between versions of Matlab.</p> <pre><code>javaaddpath('/path/to/IgnoreModifiedKeystrokesAction.jar') cmdwin = getCommandWindow(); editor = getEditor(); for t = [cmdwin,editor] defaultAction = t.getKeymap().getDefaultAction(); if ~strcmp(defaultAction.class(),'IgnoreModifiedKeystrokesAction') newAction = IgnoreModifiedKeystrokesAction(defaultAction); t.getKeymap().setDefaultAction(newAction); end end %% Subfunctions to retrieve handles to the java text pane elements function cw = getCommandWindow() try cw = handle(com.mathworks.mde.desk.MLDesktop.getInstance.getClient('Command Window').getComponent(0).getComponent(0).getComponent(0),'CallbackProperties'); assert(strcmp(cw.class(),'javahandle_withcallbacks.com.mathworks.mde.cmdwin.XCmdWndView')); catch %#ok&lt;CTCH&gt; cw_client = com.mathworks.mde.desk.MLDesktop.getInstance.getClient('Command Window'); cw = searchChildComponentsForClass(cw_client,'com.mathworks.mde.cmdwin.XCmdWndView'); end if isempty(cw) error('Unable to find the Command Window'); end end function ed = getEditor() try ed = handle(com.mathworks.mde.desk.MLDesktop.getInstance.getGroupContainer('Editor').getComponent(1).getComponent(0).getComponent(0).getComponent(0).getComponent(1).getComponent(0).getComponent(0).getComponent(0).getComponent(0).getComponent(1).getComponent(0).getComponent(0),'CallbackProperties'); assert(strcmp(ed.class(),'javahandle_withcallbacks.com.mathworks.mde.editor.EditorSyntaxTextPane')); catch %#ok&lt;CTCH&gt; ed_group = com.mathworks.mde.desk.MLDesktop.getInstance.getGroupContainer('Editor'); ed = searchChildComponentsForClass(ed_group,'com.mathworks.mde.editor.EditorSyntaxTextPane'); % TODO: When in split pane mode, there are two editor panes. Do I need % to change actionMaps/inputMaps/Keymaps on both panes? end if isempty(ed) error('Unable to find the Editor Window'); end end function obj = searchChildComponentsForClass(parent,classname) % Search Java parent object for a child component with the specified classname obj = []; if ~ismethod(parent,'getComponentCount') || ~ismethod(parent,'getComponent') return end for i=0:parent.getComponentCount()-1 child = parent.getComponent(i); if strcmp(child.class(),classname) obj = child; else obj = searchChildComponentsForClass(child,classname); end if ~isempty(obj) obj = handle(obj,'CallbackProperties'); break end end end </code></pre> <p>Now it's possible to define keybindings in the standard preferences window that use the option key!</p> <hr> <p><strong>Step 3 (optional): Remove the custom action</strong></p> <pre><code>cmdwin = getCommandWindow(); editor = getEditor(); for t = [cmdwin,editor] defaultAction = t.getKeymap().getDefaultAction(); if strcmp(defaultAction.class(),'IgnoreModifiedKeystrokesAction') oldAction = defaultAction.getOriginalAction(); t.getKeymap().setDefaultAction(oldAction); end end javarmpath('/path/to/IgnoreModifiedKeystrokesAction.jar') </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload