Support compound key combinations in GlobalKey Compound keys can now be formed by embedding a KeyCommandSet inside of a CompoundKeyCommand. The set is only enabled for a short time (250 ms) after the activation key on the CompoundKeyCommand is hit by the user. If the timeout expires, the set is disabled. If a key is selected, the set is disabled. Signed-off-by: Shawn O. Pearce <sop@google.com>
diff --git a/src/main/java/com/google/gwtexpui/globalkey/client/CompoundKeyCommand.java b/src/main/java/com/google/gwtexpui/globalkey/client/CompoundKeyCommand.java new file mode 100644 index 0000000..304d56e --- /dev/null +++ b/src/main/java/com/google/gwtexpui/globalkey/client/CompoundKeyCommand.java
@@ -0,0 +1,40 @@ +// Copyright (C) 2009 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.gwtexpui.globalkey.client; + +import com.google.gwt.event.dom.client.KeyPressEvent; + +public final class CompoundKeyCommand extends KeyCommand { + final KeyCommandSet set; + + public CompoundKeyCommand(int mask, char key, String help, KeyCommandSet s) { + super(mask, key, help); + set = s; + } + + public CompoundKeyCommand(int mask, int key, String help, KeyCommandSet s) { + super(mask, key, help); + set = s; + } + + public KeyCommandSet getSet() { + return set; + } + + @Override + public void onKeyPress(final KeyPressEvent event) { + GlobalKey.temporaryWithTimeout(set); + } +}
diff --git a/src/main/java/com/google/gwtexpui/globalkey/client/GlobalKey.java b/src/main/java/com/google/gwtexpui/globalkey/client/GlobalKey.java index 014a673..b99e63f 100644 --- a/src/main/java/com/google/gwtexpui/globalkey/client/GlobalKey.java +++ b/src/main/java/com/google/gwtexpui/globalkey/client/GlobalKey.java
@@ -20,6 +20,7 @@ import com.google.gwt.event.logical.shared.CloseEvent; import com.google.gwt.event.logical.shared.CloseHandler; import com.google.gwt.event.shared.HandlerRegistration; +import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.ui.PopupPanel; import com.google.gwt.user.client.ui.Widget; @@ -35,16 +36,29 @@ private static State global; static State active; private static CloseHandler<PopupPanel> restoreGlobal; + private static Timer restoreTimer; private static void initEvents() { if (active == null) { DocWidget.get().addKeyPressHandler(new KeyPressHandler() { @Override public void onKeyPress(final KeyPressEvent event) { - active.all.onKeyPress(event); + final KeyCommandSet s = active.live; + if (s != active.all) { + active.live = active.all; + restoreTimer.cancel(); + } + s.onKeyPress(event); } }); + restoreTimer = new Timer() { + @Override + public void run() { + active.live = active.all; + } + }; + global = new State(null); active = global; } @@ -61,6 +75,11 @@ } } + static void temporaryWithTimeout(final KeyCommandSet s) { + active.live = s; + restoreTimer.schedule(250); + } + public static void dialog(final PopupPanel panel) { initEvents(); initDialog(); @@ -127,6 +146,7 @@ final Widget root; final KeyCommandSet app; final KeyCommandSet all; + KeyCommandSet live; State(final Widget r) { root = r; @@ -136,6 +156,8 @@ all = new KeyCommandSet(); all.add(app); + + live = all; } void add(final KeyCommand k) {
diff --git a/src/main/java/com/google/gwtexpui/globalkey/client/KeyCommandSet.java b/src/main/java/com/google/gwtexpui/globalkey/client/KeyCommandSet.java index a788639..d190050 100644 --- a/src/main/java/com/google/gwtexpui/globalkey/client/KeyCommandSet.java +++ b/src/main/java/com/google/gwtexpui/globalkey/client/KeyCommandSet.java
@@ -91,8 +91,11 @@ } } for (final Iterator<KeyCommand> i = map.values().iterator(); i.hasNext();) { - if (!filter.include(i.next())) { + final KeyCommand kc = i.next(); + if (!filter.include(kc)) { i.remove(); + } else if (kc instanceof CompoundKeyCommand) { + ((CompoundKeyCommand) kc).set.filter(filter); } } }
diff --git a/src/main/java/com/google/gwtexpui/globalkey/client/KeyConstants.java b/src/main/java/com/google/gwtexpui/globalkey/client/KeyConstants.java index 3b02f33..802e349 100644 --- a/src/main/java/com/google/gwtexpui/globalkey/client/KeyConstants.java +++ b/src/main/java/com/google/gwtexpui/globalkey/client/KeyConstants.java
@@ -24,6 +24,7 @@ String keyboardShortcuts(); String closeButton(); String orOtherKey(); + String thenOtherKey(); String keyCtrl(); String keyAlt();
diff --git a/src/main/java/com/google/gwtexpui/globalkey/client/KeyConstants.properties b/src/main/java/com/google/gwtexpui/globalkey/client/KeyConstants.properties index 7714ac8..e21daf5 100644 --- a/src/main/java/com/google/gwtexpui/globalkey/client/KeyConstants.properties +++ b/src/main/java/com/google/gwtexpui/globalkey/client/KeyConstants.properties
@@ -5,6 +5,7 @@ keyboardShortcuts = Keyboard Shortcuts closeButton = Close orOtherKey = or +thenOtherKey = then keyCtrl = Ctrl keyAlt = Alt
diff --git a/src/main/java/com/google/gwtexpui/globalkey/client/KeyHelpPopup.java b/src/main/java/com/google/gwtexpui/globalkey/client/KeyHelpPopup.java index f68c5e7..6e2c276 100644 --- a/src/main/java/com/google/gwtexpui/globalkey/client/KeyHelpPopup.java +++ b/src/main/java/com/google/gwtexpui/globalkey/client/KeyHelpPopup.java
@@ -101,7 +101,7 @@ while (setitr.hasNext()) { final KeyCommandSet set = setitr.next(); int row = end[column]; - row = populate(lists, row, column, set); + row = formatGroup(lists, row, column, set); end[column] = row; if (column == 0) { column = 4; @@ -111,8 +111,82 @@ } } - private int populate(final Grid lists, int row, final int col, + private int formatGroup(final Grid lists, int row, final int col, final KeyCommandSet set) { + if (set.isEmpty()) { + return row; + } + + if (lists.getRowCount() < row + 1) { + lists.resizeRows(row + 1); + } + lists.setText(row, col + 2, set.getName()); + lists.getCellFormatter().addStyleName(row, col + 2, S + "-GroupTitle"); + row++; + + return formatKeys(lists, row, col, set, null); + } + + private int formatKeys(final Grid lists, int row, final int col, + final KeyCommandSet set, final SafeHtml prefix) { + final CellFormatter fmt = lists.getCellFormatter(); + final int initialRow = row; + final List<KeyCommand> keys = sort(set); + if (lists.getRowCount() < row + keys.size()) { + lists.resizeRows(row + keys.size()); + } + FORMAT_KEYS: for (int i = 0; i < keys.size(); i++) { + final KeyCommand k = keys.get(i); + + if (k instanceof CompoundKeyCommand) { + final SafeHtmlBuilder b = new SafeHtmlBuilder(); + b.append(k.describeKeyStroke()); + row = formatKeys(lists, row, col, ((CompoundKeyCommand) k).getSet(), b); + continue; + } + + for (int prior = 0, r = initialRow; prior < i; prior++) { + if (KeyCommand.same(keys.get(prior), k)) { + final SafeHtmlBuilder b = new SafeHtmlBuilder(); + b.append(SafeHtml.get(lists, r, col + 0)); + b.append(" "); + b.append(Util.C.orOtherKey()); + b.append(" "); + if (prefix != null) { + b.append(prefix); + b.append(" "); + b.append(Util.C.thenOtherKey()); + b.append(" "); + } + b.append(k.describeKeyStroke()); + SafeHtml.set(lists, r, col + 0, b); + continue FORMAT_KEYS; + } + } + + if (prefix != null) { + final SafeHtmlBuilder b = new SafeHtmlBuilder(); + b.append(prefix); + b.append(" "); + b.append(Util.C.thenOtherKey()); + b.append(" "); + b.append(k.describeKeyStroke()); + SafeHtml.set(lists, row, col + 0, b); + } else { + SafeHtml.set(lists, row, col + 0, k.describeKeyStroke()); + } + lists.setText(row, col + 1, ":"); + lists.setText(row, col + 2, k.getHelpText()); + + fmt.addStyleName(row, col + 0, S + "-TableKeyStroke"); + fmt.addStyleName(row, col + 1, S + "-TableSeparator"); + row++; + } + + return row; + } + + private List<KeyCommand> sort(final KeyCommandSet set) { final List<KeyCommand> keys = new ArrayList<KeyCommand>(set.getKeys()); Collections.sort(keys, new Comparator<KeyCommand>() { @Override @@ -125,45 +199,6 @@ return 0; } }); - if (keys.isEmpty()) { - return row; - } - - if (lists.getRowCount() < row + 1 + keys.size()) { - lists.resizeRows(row + 1 + keys.size()); - } - - final CellFormatter fmt = lists.getCellFormatter(); - lists.setText(row, col + 2, set.getName()); - fmt.addStyleName(row, col + 2, S + "-GroupTitle"); - row++; - - final int initialRow = row; - FORMAT_KEYS: for (int i = 0; i < keys.size(); i++) { - final KeyCommand k = keys.get(i); - - for (int prior = 0, r = initialRow; prior < i; prior++) { - if (KeyCommand.same(keys.get(prior), k)) { - final SafeHtmlBuilder b = new SafeHtmlBuilder(); - b.append(SafeHtml.get(lists, r, col + 0)); - b.append(" "); - b.append(Util.C.orOtherKey()); - b.append(" "); - b.append(k.describeKeyStroke()); - SafeHtml.set(lists, r, col + 0, b); - continue FORMAT_KEYS; - } - } - - SafeHtml.set(lists, row, col + 0, k.describeKeyStroke()); - lists.setText(row, col + 1, ":"); - lists.setText(row, col + 2, k.getHelpText()); - - fmt.addStyleName(row, col + 0, S + "-TableKeyStroke"); - fmt.addStyleName(row, col + 1, S + "-TableSeparator"); - row++; - } - - return row; + return keys; } }