Mailing Lists: Apple Mailing Lists

Image of Mac OS face in stamp
 
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

MetalLookAndFeel with Mac-appropriate key bindings, revisited



I posted here over a year ago looking for a way to use the "Metal" look-and-feel on the Mac, but with Mac-appropriate key bindings that use the Command key instead of the Ctrl key. This isn't because I love Metal. I think it's kind of ugly in fact, but I've grown tired of the many problems I've had with the Aqua L&F, and I haven't wanted to add the bulk of something like Quaqua to a web applet.

The solution I ended up using previously didn't really thrill me. I'd been calling a utility method, passing in GUI components individually to remap each component's bindings by getting their InputMaps, searching for "ctrl" Keystrokes, and replacing those InputMap entries with "meta" (Command) key equivalents.

That worked okay for the most part, but things like JOptionPanes with text entry fields still didn't work right. (I had thought of a clunky work-around for that, but I didn't bother implementing it.) I also could have made a utility method to recursively search views for components to fix up, but that's not as clean a solution as I'd been hoping for either.

Now, however, I've finally figured out how to do this the right way -- or if not THE right way, at least in a better, more satisfactory way, so that every GUI component is automatically born using the right Mac key bindings without further tweaking, and so that I don't have to explicitly state every individual Ctrl->Command modified key binding for all of the different GUI components that I want to have remapped for Cut, Copy, Paste, etc., etc.


private void setupUI() { try { LookAndFeel laf = new javax.swing.plaf.metal.MetalLookAndFeel() { protected void initComponentDefaults(UIDefaults table) { super.initComponentDefaults(table); fixMacKeyBindings(table); } };

      UIManager.setLookAndFeel(laf);
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }

  private static final Pattern ctrlPat = Pattern.compile("\\bctrl\\b");

// Replaces all Ctrl-key KeyStrokes found within InputMaps with Command-key equivalents.
//
public static void fixMacKeyBindings(UIDefaults uiDefaults)
{
if (Util.isMac()) { // My own utility function -- substitute your own test as needed
Object[] keys = uiDefaults.keySet().toArray(); // Copied to prevent concurrent modification issues.


      for (Object key : keys) {
        Object  value = uiDefaults.get(key);

        if (value instanceof InputMap) {
          InputMap      map = (InputMap) value;
          KeyStroke[]   keyStrokes = map.keys();

          if (keyStrokes != null) {
            for (KeyStroke keyStroke : keyStrokes) {
              String  keyString = keyStroke.toString();

              if (keyString.indexOf("ctrl ") >= 0) {
                Object  action = map.get(keyStroke);

keyString = ctrlPat.matcher(keyString).replaceAll("meta");
map.remove(keyStroke);
keyStroke = KeyStroke.getKeyStroke(keyString);
map.put(keyStroke, action);
}
}
}
}
}
}
}



For some reason this technique only works properly when I create an L&F object and override the initComponentDefaults() method. Calling fixMacKeyBindings(laf.getDefaults()) after instantiating the L&F, or calling fixMacKeyBindings() with UIManager.getDefaults() or UIManager.getLookAndFeel().getDefaults() as an argument doesn't work. I'm guessing that key bindings must get cached somewhere along the line so that it's too late to fix them if you don't catch and modify the key bindings during an L&F's initialization.


This technique also works well with JGoodies PlasticLookAndFeel and PlasticXPLookAndFeel, L&Fs that look nice enough and neutral enough that I'm happy using them across multiple platforms in some cases. Now I can have an interface that looks the same on all platforms while still matching platform-specific user expectations for keyboard usage.
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Java-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/java-dev/email@hidden


This email sent to email@hidden


Visit the Apple Store online or at retail locations.
1-800-MY-APPLE

Contact Apple | Terms of Use | Privacy Policy

Copyright © 2007 Apple Inc. All rights reserved.