Skip to content

Commit

Permalink
Added shortcut feature for vaadin 7 (#10)
Browse files Browse the repository at this point in the history
* Added support for shortcuts

* Update headers
  • Loading branch information
mcollovati authored Jul 16, 2018
1 parent 70ff694 commit 0fef1c7
Show file tree
Hide file tree
Showing 15 changed files with 340 additions and 18 deletions.
2 changes: 1 addition & 1 deletion enhanced-window-opener-addon/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>org.vaadin.addon</groupId>
<artifactId>enhanced-window-opener-root</artifactId>
<version>0.1.1</version>
<version>0.1.2</version>
<relativePath>../</relativePath>
</parent>
<artifactId>enhanced-window-opener</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2016 Marco Collovati ([email protected])
* Copyright (C) 2016-2018 Marco Collovati ([email protected])
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -18,6 +18,7 @@
import java.time.Instant;
import java.util.Objects;

import com.vaadin.event.ShortcutListener;
import com.vaadin.server.AbstractClientConnector;
import com.vaadin.server.BrowserWindowOpener;
import com.vaadin.server.Resource;
Expand Down Expand Up @@ -142,6 +143,19 @@ public EnhancedBrowserWindowOpener popupBlockerWorkaround(boolean active) {
return this;
}

public EnhancedBrowserWindowOpener withShortcut(int keyCode, int... modifiers) {
getState().shortcut = new EnhancedBrowserWindowOpenerState.Shortcut(keyCode, modifiers);
return this;
}
public EnhancedBrowserWindowOpener withShortcut(ShortcutListener shortcutListener) {
return withShortcut(shortcutListener.getKeyCode(), shortcutListener.getModifiers());
}

public EnhancedBrowserWindowOpener withoutShortcut() {
getState().shortcut = null;
return this;
}

/**
* Sets a {@code resource} for this instance whose content will be generated
* when the window will be opened.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2016 Marco Collovati ([email protected])
* Copyright (C) 2016-2018 Marco Collovati ([email protected])
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2016 Marco Collovati ([email protected])
* Copyright (C) 2016-2018 Marco Collovati ([email protected])
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -18,14 +18,27 @@
import java.util.Map;

import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.KeyDownEvent;
import com.google.gwt.event.dom.client.KeyDownHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.http.client.URL;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.KeyboardListener;
import com.google.gwt.user.client.ui.KeyboardListenerCollection;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Widget;
import com.vaadin.client.ComponentConnector;
import com.vaadin.client.ServerConnector;
import com.vaadin.client.VConsole;
import com.vaadin.client.WidgetUtil;
import com.vaadin.client.annotations.OnStateChange;
import com.vaadin.client.extensions.BrowserWindowOpenerConnector;
import com.vaadin.client.ui.VMenuBar;
import com.vaadin.client.ui.VUI;
import com.vaadin.client.ui.menubar.MenuBarConnector;
import com.vaadin.shared.ui.BrowserWindowOpenerState;
import com.vaadin.shared.ui.Connect;
Expand All @@ -42,6 +55,8 @@ public class EnhancedBrowserWindowOpenerConnector extends BrowserWindowOpenerCon
private JavaScriptObject window;
private HandlerRegistration menuClickHandlerReg;

private HandlerRegistration shortcutHandler;
private ShortcutKeyCombination shortcutKeyCombination;

@Override
public void onClick(ClickEvent event) {
Expand All @@ -54,6 +69,8 @@ public void onClick(ClickEvent event) {

@Override
public void onUnregister() {
removeShortcutHandler();
shortcutKeyCombination = null;
window = null;
super.onUnregister();
if (menuClickHandlerReg != null) {
Expand Down Expand Up @@ -93,6 +110,79 @@ public void onMenuItemSelected(ServerSideIdAwareMenuItem.MenuItemSelectedEvent e
}, ServerSideIdAwareMenuItem.MenuItemSelectedEvent.getType());
}

@OnStateChange("shortcut")
private void onShortcutChanged() {
VConsole.log("=============== Shortcut changed " + getState().shortcut);


ShortcutKeyCombination newShortcutKeyCombination;

if (getState().shortcut == null) {
removeShortcutHandler();
shortcutKeyCombination = null;
} else {
shortcutKeyCombination = new ShortcutKeyCombination(
getState().shortcut.keyCode, getState().shortcut.modifiers
);
if (shortcutHandler == null) {
final VUI ui = findUI();
Widget shortcutContextWidget = ui;
if (getConnection().getConfiguration().isStandalone()) {
// Listen to body for standalone apps (#19392)
shortcutContextWidget = RootPanel.get(); // document body
}

if (shortcutContextWidget != null) {
// Only react to body and elements inside the UI
shortcutHandler = shortcutContextWidget.addDomHandler(new KeyDownHandler() {
@Override
public void onKeyDown(KeyDownEvent event) {
Element target = Element.as(event.getNativeEvent().getEventTarget());
if (target == Document.get().getBody()
|| ui.getElement().isOrHasChild(target)) {
// Only react to body and elements inside the UI
Event castedEvent = event.getNativeEvent().cast();
EnhancedBrowserWindowOpenerConnector.this.handleKeyboardEvent(castedEvent);
}
}
}, KeyDownEvent.getType());
} else {
// TODO: log
}
}
}
}



private void removeShortcutHandler() {
if (shortcutHandler != null) {
shortcutHandler.removeHandler();
}
}

private void handleKeyboardEvent(final Event event) {
final char keyCode = (char) DOM.eventGetKeyCode(event);
if (keyCode == 0 || shortcutKeyCombination == null) {
return;
}
final int modifiers = KeyboardListenerCollection
.getKeyboardModifiers(event);
final ShortcutKeyCombination kc = new ShortcutKeyCombination(keyCode, modifiers);

if (shortcutKeyCombination.equals(kc)) {
onClick(null);
}
}

private VUI findUI() {
if (getParent() instanceof ComponentConnector) {
Element element = ((ComponentConnector) getParent()).getWidget().getElement();
return WidgetUtil.findWidget(element, VUI.class);
}
return null;
}

@OnStateChange("lastUpdated")
private void onLastUpdateChanged() {
if (!getState().clientSide && getState().lastUpdated > 0) {
Expand Down Expand Up @@ -143,6 +233,7 @@ private String addParametersAndFragment(String url) {
return url;
}


private static native JavaScriptObject openWindow(String name, String features) /*-{
return $wnd.open(undefined, name, features);
}-*/;
Expand All @@ -164,3 +255,78 @@ private static native void wrapMenu(VMenuBar hostReference) /*-{
}
}-*/;
}

/**
* Code taken from {@link com.vaadin.client.ui.ShortcutActionHandler}
*
*
* Copyright 2000-2018 Vaadin Ltd.
*
* 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.
*/

class ShortcutKeyCombination {

public static final int SHIFT = 16;
public static final int CTRL = 17;
public static final int ALT = 18;
public static final int META = 91;

char keyCode = 0;
private int modifiersMask;

public ShortcutKeyCombination() {
}

ShortcutKeyCombination(char kc, int modifierMask) {
keyCode = kc;
modifiersMask = modifierMask;
}

ShortcutKeyCombination(int kc, int[] modifiers) {
keyCode = (char) kc;

modifiersMask = 0;
if (modifiers != null) {
for (int modifier : modifiers) {
switch (modifier) {
case ALT:
modifiersMask = modifiersMask
| KeyboardListener.MODIFIER_ALT;
break;
case CTRL:
modifiersMask = modifiersMask
| KeyboardListener.MODIFIER_CTRL;
break;
case SHIFT:
modifiersMask = modifiersMask
| KeyboardListener.MODIFIER_SHIFT;
break;
case META:
modifiersMask = modifiersMask
| KeyboardListener.MODIFIER_META;
break;
default:
break;
}
}
}
}

public boolean equals(ShortcutKeyCombination other) {
if (keyCode == other.keyCode && modifiersMask == other.modifiersMask) {
return true;
}
return false;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2016-2017 Marco Collovati ([email protected])
* Copyright (C) 2016-2018 Marco Collovati ([email protected])
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2016 Marco Collovati ([email protected])
* Copyright (C) 2016-2018 Marco Collovati ([email protected])
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -15,6 +15,9 @@
*/
package org.vaadin.addon.ewopener.shared;

import java.io.Serializable;
import java.util.Arrays;

import com.vaadin.shared.ui.BrowserWindowOpenerState;

public class EnhancedBrowserWindowOpenerState extends BrowserWindowOpenerState {
Expand All @@ -26,4 +29,24 @@ public class EnhancedBrowserWindowOpenerState extends BrowserWindowOpenerState {
public boolean popupBlockerWorkaround = false;

public int menuItem = 0;
public Shortcut shortcut;

public static class Shortcut implements Serializable {
public int keyCode;

public int[] modifiers;

public Shortcut() {
}

public Shortcut(int keyCode, int[] modifiers) {
this.keyCode = keyCode;
this.modifiers = modifiers;
}

@Override
public String toString() {
return "KeyCode: " + keyCode + " - modifiers: [" + Arrays.toString(modifiers) + "]";
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2016 Marco Collovati ([email protected])
* Copyright (C) 2016-2018 Marco Collovati ([email protected])
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down
2 changes: 1 addition & 1 deletion enhanced-window-opener-demo/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>org.vaadin.addon</groupId>
<artifactId>enhanced-window-opener-root</artifactId>
<version>0.1.1</version>
<version>0.1.2</version>
<relativePath>../</relativePath>
</parent>
<artifactId>enhanced-window-opener-demo</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright (C) 2016-2018 Marco Collovati ([email protected])
*
* 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 org.vaadin.addon.ewopener.demo;

import com.vaadin.annotations.Theme;
import com.vaadin.server.VaadinRequest;
import com.vaadin.ui.Label;
import com.vaadin.ui.UI;

@Theme("demo")
public class AboutUI extends UI {
@Override
protected void init(VaadinRequest request) {
setContent(new Label("EnhancedWindowOpener"));
}
}
Loading

0 comments on commit 0fef1c7

Please sign in to comment.