alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 Sun Public License Notice
 * 
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 * 
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.netbeans.editor;

import java.util.ArrayList;
import java.util.Arrays;
import javax.swing.text.JTextComponent;
import javax.swing.KeyStroke;
import javax.swing.Action;

/**
* Extension of JTextComponent.KeyBinding to hold several successive keystrokes.
* The binding containing null key(s) is assumed to assign the default action.
*
* @author Miloslav Metelka
* @version 1.00
*/

public class MultiKeyBinding extends JTextComponent.KeyBinding
    implements java.io.Externalizable {

    /** Successive keystroke. They must be pressed in the order they
    * are stored in the array in order to invoke the associated action.
    */
    public KeyStroke[] keys;

    static final long serialVersionUID =-8602816556604003688L;

    /** Constructor for serialization */
    public MultiKeyBinding() {
        super(null, null);
    }

    /** Constructor for assigning keystroke sequence to action
    * @param keys successive keystroke that must be pressed in order
    *    to invoke action
    * @param actionName action that will be invoked. Action is resolved
    *    from name by calling kit.getActions() after the kit is constructed
    */
    public MultiKeyBinding(KeyStroke[] keys, String actionName) {
        super(null, actionName);
        this.keys = keys;
    }

    /** Compatibility constructor */
    public MultiKeyBinding(KeyStroke key, String actionName) {
        super(key, actionName);
    }

    /** Constructor for existing KeyBinding */
    public MultiKeyBinding(JTextComponent.KeyBinding kb) {
        this(kb.key, kb.actionName);
    }

    public boolean equals(Object o) {
        if (o instanceof MultiKeyBinding) {
            MultiKeyBinding kb = (MultiKeyBinding)o;

            // Compare action names
            if (actionName == null) {
                if (kb.actionName != null) {
                    return false;
                }
            } else {
                if (!actionName.equals(kb.actionName)) {
                    return false;
                }
            }

            // Action names match, now compare action keys
            if (keys == null) {
                if (kb.keys == null) {
                    return (key == null && kb.key == null)
                           || (key != null && key.equals(kb.key));
                } else {
                    return (kb.keys.length == 1
                            && ((key == null && kb.keys[0] == null)
                                || (key != null && key.equals(kb.keys[0]))));
                }
            } else { // keys != null
                if (kb.keys != null) {
                    return Arrays.equals(keys, kb.keys);
                } else { // kb.keys == null
                    return (keys.length == 1
                            && ((kb.key == null && keys[0] == null)
                                || (kb.key != null && kb.key.equals(keys[0]))));
                }
            }
        }
        return false;
    }

    /** Add or replace key bindings array by changes given in
    * the second bindings array
    * @param target target list of bindings
    * @param changes list of changes to apply:
    *  binding containing the non-null keystroke(s) and non-null action
    *    will add the binding or replace the old binding with the same
    *    keystroke(s) in the target array,
    *  binding of the non-null keystroke(s) and null action removes
    *    the binding for that keystroke from the target array (if it existed)
    *  binding containing null keystroke and non-null action adds
    *    or replaces default action
    */
    public static void updateKeyBindings(JTextComponent.KeyBinding[] target,
                                         JTextComponent.KeyBinding[] changes) {
        ArrayList tgt = new ArrayList(Arrays.asList(target));
        MultiKeyBinding tmp = new MultiKeyBinding(new KeyStroke[1], null);
        MultiKeyBinding cur;
        for (int i = 0; i < changes.length; i++) {
            if (changes[i] instanceof MultiKeyBinding) {
                cur = (MultiKeyBinding)changes[i];
                if (cur.keys == null) { // single key multi binding
                    tmp.keys[0] = cur.key;
                    tmp.actionName = cur.actionName;
                    cur = tmp;
                }
            } else { // simulate multi binding
                tmp.keys[0] = changes[i].key;
                tmp.actionName = changes[i].actionName;
                cur = tmp;
            }
            // cycle through all bindings
            boolean matched = false;
            for (int j = 0; j < tgt.size(); j++) {
                JTextComponent.KeyBinding kb = (JTextComponent.KeyBinding)tgt.get(j);
                if (kb instanceof MultiKeyBinding) {
                    MultiKeyBinding mkb = (MultiKeyBinding)kb;
                    if (mkb.keys == null) { // single key multi binding
                        if (cur.keys.length == 1 && cur.keys[0].equals(mkb.key)) { // found
                            if (mkb.actionName == null) { // remove
                                tgt.remove(i);
                            } else { // replace
                                tgt.set(i, mkb);
                            }
                            matched = true;
                            break;
                        }
                    } else { // multi binding
                        if (cur.keys.length == mkb.keys.length) {
                            matched = true;
                            for (int k = 0; k < cur.keys.length; k++) {
                                if (!cur.keys[k].equals(mkb.keys[k])) {
                                    matched = false;
                                    break;
                                }
                            }
                            if (matched) {
                                if (mkb.actionName == null) { // remove
                                    tgt.remove(i);
                                } else { // replace
                                    tgt.set(i, mkb);
                                }
                                break;
                            }
                        }
                    }
                } else { // single key binding
                    if (cur.keys.length == 1 && cur.keys[0].equals(kb.key)) { // found
                        if (kb.actionName == null) { // remove
                            tgt.remove(i);
                        } else { // replace
                            tgt.set(i, kb);
                        }
                        matched = true;
                        break;
                    }
                }
            }
            if (!matched) {
                tgt.add(changes[tgt.size()]);
            }
        }
    }

    public void readExternal(java.io.ObjectInput in)
    throws java.io.IOException, ClassNotFoundException {
        Object obj = in.readObject ();

        if( obj instanceof Integer ) { // new settings format
            int len = ((Integer)obj).intValue();
            if( len >= 0 ) {
                keys = new KeyStroke[ len ];
                for( int i=0; i

favorite books

'; var post = ''; if (adblock) { var str = books.slice(0,3).join(" "); div.insertAdjacentHTML('beforeend', pre + str + post); } else { var str = books.slice(0,1).join(" "); div.insertAdjacentHTML('beforeend', pre + str + post); }