IDEMPIERE-599 Zk: Clean up shortcut key implementation.

This commit is contained in:
Heng Sin Low 2013-01-31 23:51:12 +08:00
parent 7d24e083c3
commit a1f7c7c1d5
9 changed files with 167 additions and 63 deletions

View File

@ -48,6 +48,7 @@ import org.compiere.model.MUser;
import org.compiere.util.CLogger;
import org.compiere.util.Env;
import org.compiere.util.Language;
import org.zkforge.keylistener.Keylistener;
import org.zkoss.web.Attributes;
import org.zkoss.web.servlet.Servlets;
import org.zkoss.zk.ui.Component;
@ -103,6 +104,8 @@ public class AdempiereWebUI extends Window implements EventListener<Event>, IWeb
private UserPreference userPreference;
private Keylistener keyListener;
private static final CLogger logger = CLogger.getCLogger(AdempiereWebUI.class);
public static final String EXECUTION_CARRYOVER_SESSION_KEY = "execution.carryover";
@ -336,6 +339,19 @@ public class AdempiereWebUI extends Window implements EventListener<Event>, IWeb
{
BrowserToken.remove();
}
keyListener = new Keylistener();
keyListener.setPage(this.getPage());
keyListener.setCtrlKeys("@a@c@d@e@f@h@n@o@p@r@s@t@z@x@#left@#right@#up@#down@#home@#end#enter");
keyListener.setAutoBlur(false);
}
/**
* @return key listener
*/
@Override
public Keylistener getKeylistener() {
return keyListener;
}
private void createDesktop()
@ -377,6 +393,11 @@ public class AdempiereWebUI extends Window implements EventListener<Event>, IWeb
protected Session logout0() {
Session session = Executions.getCurrent().getDesktop().getSession();
if (keyListener != null) {
keyListener.detach();
keyListener = null;
}
//stop background thread
if (appDesktop != null)
appDesktop.logout();

View File

@ -15,6 +15,7 @@ package org.adempiere.webui;
import org.adempiere.webui.desktop.IDesktop;
import org.adempiere.webui.util.UserPreference;
import org.compiere.model.MUser;
import org.zkforge.keylistener.Keylistener;
/**
*
@ -57,4 +58,9 @@ public interface IWebClient {
*/
public void changeRole(MUser user);
/**
* @return keylistener
*/
public abstract Keylistener getKeylistener();
}

View File

@ -44,6 +44,7 @@ import org.adempiere.webui.editor.IZoomableEditor;
import org.adempiere.webui.editor.WButtonEditor;
import org.adempiere.webui.editor.WEditor;
import org.adempiere.webui.editor.WEditorPopupMenu;
import org.adempiere.webui.editor.WImageEditor;
import org.adempiere.webui.editor.WPaymentEditor;
import org.adempiere.webui.editor.WebEditorFactory;
import org.adempiere.webui.event.ContextMenuListener;
@ -923,7 +924,8 @@ DataStatusListener, IADTabpanel, IdSpace
}
if (toFocus == null) {
if (editor.isVisible() && editor.isReadWrite() && editor.getComponent().getParent() != null) {
if (editor.isVisible() && editor.isReadWrite() && editor.getComponent().getParent() != null
&& !(editor instanceof WImageEditor)) {
toFocus = editor;
}
}

View File

@ -30,8 +30,8 @@ import org.adempiere.webui.component.Tabpanel;
import org.adempiere.webui.panel.ITabOnCloseHandler;
import org.adempiere.webui.session.SessionManager;
import org.compiere.util.CLogger;
import org.zkforge.keylistener.Keylistener;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Page;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
@ -59,8 +59,6 @@ public class ADWindowContent extends AbstractADWindowContent
private Div contentArea;
private Keylistener keyListener;
public ADWindowContent(Properties ctx, int windowNo, int adWindowId)
{
super(ctx, windowNo, adWindowId);
@ -68,7 +66,7 @@ public class ADWindowContent extends AbstractADWindowContent
protected Component doCreatePart(Component parent)
{
layout = new Vlayout();
layout = new ADWindowVlayout(this);
if (parent != null) {
layout.setParent(parent);
layout.setSclass("adwindow-layout");
@ -114,14 +112,7 @@ public class ADWindowContent extends AbstractADWindowContent
((Tabpanel)parent).setOnCloseHandler(handler);
}
if (keyListener != null)
keyListener.detach();
keyListener = new Keylistener();
statusBar.appendChild(keyListener);
keyListener.setCtrlKeys("#f1#f2#f3#f4#f5#f6#f7#f8#f9#f10#f11#f12^f^i^n^s^d@#left@#right@#up@#down@#pgup@#pgdn@p^p@z@x#enter");
keyListener.addEventListener(Events.ON_CTRL_KEY, toolbar);
keyListener.addEventListener(Events.ON_CTRL_KEY, this);
keyListener.setAutoBlur(false);
SessionManager.getSessionApplication().getKeylistener().addEventListener(Events.ON_CTRL_KEY, this);
return layout;
}
@ -167,5 +158,26 @@ public class ADWindowContent extends AbstractADWindowContent
SessionManager.getAppDesktop().unregisterWindow(getWindowNo());
}
}
}
}
static class ADWindowVlayout extends Vlayout {
/**
* generated serial id
*/
private static final long serialVersionUID = 6104341168705201721L;
private ADWindowContent content;
protected ADWindowVlayout(ADWindowContent content) {
super();
this.content = content;
}
@Override
public void onPageDetached(Page page) {
super.onPageDetached(page);
try {
SessionManager.getSessionApplication().getKeylistener().removeEventListener(Events.ON_CTRL_KEY, content);
} catch (Exception e){}
}
}
}

View File

@ -44,6 +44,7 @@ import org.compiere.util.Env;
import org.compiere.util.Msg;
import org.zkoss.image.AImage;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Page;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
@ -139,27 +140,41 @@ public class ADWindowToolbar extends FToolbar implements EventListener<Event>
LayoutUtils.addSclass("adwindow-toolbar", this);
btnIgnore = createButton("Ignore", "Ignore", "Ignore");
btnIgnore.setTooltiptext(btnIgnore.getTooltiptext()+ " Alt+Z");
addSeparator();
btnHelp = createButton("Help", "Help","Help");
btnHelp.setTooltiptext(btnHelp.getTooltiptext()+ " Alt+H");
btnNew = createButton("New", "New", "New");
btnNew.setTooltiptext(btnNew.getTooltiptext()+ " Alt+N");
btnCopy = createButton("Copy", "Copy", "Copy");
btnCopy.setTooltiptext(btnCopy.getTooltiptext()+ " Alt+C");
btnDelete = createButton("Delete", "Delete", "Delete");
btnDelete.setTooltiptext(btnDelete.getTooltiptext()+ " Alt+D");
btnDeleteSelection = createButton("DeleteSelection", "DeleteSelection", "DeleteSelection");
btnSave = createButton("Save", "Save", "Save");
btnSave.setTooltiptext(btnSave.getTooltiptext()+ " Alt+S");
btnSaveAndCreate = createButton("SaveCreate", "SaveCreate", "SaveCreate");
btnSaveAndCreate.setTooltiptext(btnSaveAndCreate.getTooltiptext()+ " Alt+A");
addSeparator();
btnRefresh = createButton("Refresh", "Refresh", "Refresh");
btnRefresh.setTooltiptext(btnRefresh.getTooltiptext()+ " Alt+E");
btnFind = createButton("Find", "Find", "Find");
btnFind.setTooltiptext(btnFind.getTooltiptext()+ " Alt+F");
btnAttachment = createButton("Attachment", "Attachment", "Attachment");
btnChat = createButton("Chat", "Chat", "Chat");
btnGridToggle = createButton("Toggle", "Multi", "Multi");
btnGridToggle.setTooltiptext(btnGridToggle.getTooltiptext()+ " Alt+T");
addSeparator();
btnParentRecord = createButton("ParentRecord", "Parent", "Parent");
btnParentRecord.setTooltiptext(btnParentRecord.getTooltiptext()+ " Alt+Up");
btnDetailRecord = createButton("DetailRecord", "Detail", "Detail");
btnDetailRecord.setTooltiptext(btnDetailRecord.getTooltiptext()+ " Alt+Down");
addSeparator();
btnReport = createButton("Report", "Report", "Report");
btnReport.setTooltiptext(btnReport.getTooltiptext()+ " Alt+R");
btnArchive = createButton("Archive", "Archive", "Archive");
btnPrint = createButton("Print", "Print", "Print");
btnPrint.setTooltiptext(btnPrint.getTooltiptext()+ " Alt+P");
addSeparator();
btnLock = createButton("Lock", "Lock", "Lock"); // Elaine 2008/12/04
btnLock.setVisible(isPersonalLock);
@ -174,6 +189,7 @@ public class ADWindowToolbar extends FToolbar implements EventListener<Event>
btnCustomize.setDisabled(false);
btnProcess= createButton("Process", "Process", "Process");
btnProcess.setTooltiptext(btnProcess.getTooltiptext()+ " Alt+O");
btnProcess.setDisabled(false);
@ -255,29 +271,21 @@ public class ADWindowToolbar extends FToolbar implements EventListener<Event>
private void configureKeyMap()
{
keyMap.put(KeyEvent.F1, btnHelp);
keyMap.put(KeyEvent.F2, btnNew);
keyMap.put(KeyEvent.F3, btnDelete);
keyMap.put(KeyEvent.F4, btnSave);
keyMap.put(KeyEvent.F5, btnRefresh);
keyMap.put(KeyEvent.F6, btnFind);
keyMap.put(KeyEvent.F7, btnAttachment);
keyMap.put(KeyEvent.F8, btnGridToggle);
keyMap.put(KeyEvent.F11, btnReport);
keyMap.put(KeyEvent.F12, btnPrint);
altKeyMap.put(KeyEvent.LEFT, btnParentRecord);
altKeyMap.put(KeyEvent.RIGHT, btnDetailRecord);
altKeyMap.put(VK_P, btnReport);
altKeyMap.put(VK_H, btnHelp);
altKeyMap.put(VK_N, btnNew);
altKeyMap.put(VK_D, btnDelete);
altKeyMap.put(VK_S, btnSave);
altKeyMap.put(VK_A, btnSaveAndCreate);
altKeyMap.put(VK_C, btnCopy);
altKeyMap.put(VK_E, btnRefresh);
altKeyMap.put(VK_T, btnGridToggle);
altKeyMap.put(KeyEvent.UP, btnParentRecord);
altKeyMap.put(KeyEvent.DOWN, btnDetailRecord);
altKeyMap.put(VK_F, btnFind);
altKeyMap.put(VK_Z, btnIgnore);
ctrlKeyMap.put(VK_I, btnProductInfo);
ctrlKeyMap.put(VK_P, btnPrint);
ctrlKeyMap.put(VK_N, btnNew);
ctrlKeyMap.put(VK_S, btnSave);
ctrlKeyMap.put(VK_Q, btnSaveAndCreate);
ctrlKeyMap.put(VK_D, btnDelete);
ctrlKeyMap.put(VK_F, btnFind);
altKeyMap.put(VK_R, btnReport);
altKeyMap.put(VK_P, btnPrint);
altKeyMap.put(VK_O, btnProcess);
}
protected void addSeparator()
@ -311,7 +319,7 @@ public class ADWindowToolbar extends FToolbar implements EventListener<Event>
} else if (eventName.equals(Events.ON_CTRL_KEY))
{
KeyEvent keyEvent = (KeyEvent) event;
if (isRealVisible()) {
if (LayoutUtils.isReallyVisible(this)) {
//filter same key event that is too close
//firefox fire key event twice when grid is visible
long time = System.currentTimeMillis();
@ -498,18 +506,6 @@ public class ADWindowToolbar extends FToolbar implements EventListener<Event>
}
}
private boolean isRealVisible() {
if (!isVisible())
return false;
Component parent = this.getParent();
while (parent != null) {
if (!parent.isVisible())
return false;
parent = parent.getParent();
}
return true;
}
/**
*
* @param visible
@ -649,4 +645,20 @@ public class ADWindowToolbar extends FToolbar implements EventListener<Event>
toolbarCustomBtn.dynamicDisplay();
}
}
@Override
public void onPageDetached(Page page) {
super.onPageDetached(page);
try {
SessionManager.getSessionApplication().getKeylistener().removeEventListener(Events.ON_CTRL_KEY, this);
} catch (Exception e) {}
}
@Override
public void onPageAttached(Page newpage, Page oldpage) {
super.onPageAttached(newpage, oldpage);
if (newpage != null) {
SessionManager.getSessionApplication().getKeylistener().addEventListener(Events.ON_CTRL_KEY, this);
}
}
}

View File

@ -140,7 +140,9 @@ import org.zkoss.zul.Window.Mode;
public abstract class AbstractADWindowContent extends AbstractUIPart implements ToolbarListener,
EventListener<Event>, DataStatusListener, ActionListener
{
private static final String ON_DEFER_SET_DETAILPANE_SELECTION_EVENT = "onDeferSetDetailpaneSelection";
private static final String ON_FOCUS_DEFER_EVENT = "onFocusDefer";
private static final String ON_DEFER_SET_DETAILPANE_SELECTION_EVENT = "onDeferSetDetailpaneSelection";
private static final CLogger logger;
@ -216,6 +218,7 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements
Component comp = super.createPart(parent);
comp.addEventListener(LayoutUtils.ON_REDRAW_EVENT, this);
comp.addEventListener(ON_DEFER_SET_DETAILPANE_SELECTION_EVENT, this);
comp.addEventListener(ON_FOCUS_DEFER_EVENT, this);
return comp;
}
@ -265,7 +268,7 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements
private void focusToTabpanel(IADTabpanel adTabPanel ) {
if (adTabPanel != null && adTabPanel instanceof HtmlBasedComponent) {
((HtmlBasedComponent)adTabPanel).focus();
Events.echoEvent(ON_FOCUS_DEFER_EVENT, getComponent(), (HtmlBasedComponent)adTabPanel);
}
}
@ -1041,6 +1044,10 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements
Integer[] data = (Integer[]) event.getData();
adTabbox.setDetailPaneSelectedTab(data[0], data[1]);
}
else if (event.getName().equals(ON_FOCUS_DEFER_EVENT)) {
HtmlBasedComponent comp = (HtmlBasedComponent) event.getData();
comp.focus();
}
}
private void setActiveTab(final int newTabIndex, final Callback<Boolean> callback) {
@ -1695,6 +1702,8 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements
}
if (dirtyTabpanel != null)
focusToTabpanel(dirtyTabpanel);
else
focusToActivePanel();
updateToolbar();
}

View File

@ -30,6 +30,7 @@ import org.adempiere.webui.component.ToolBarButton;
import org.adempiere.webui.component.Window;
import org.adempiere.webui.component.ZkCssHelper;
import org.adempiere.webui.event.ToolbarListener;
import org.adempiere.webui.session.SessionManager;
import org.adempiere.webui.window.WRecordInfo;
import org.compiere.model.DataStatusEvent;
import org.compiere.model.MRole;
@ -136,8 +137,10 @@ public class BreadCrumb extends Div implements EventListener<Event> {
ToolBar toolbar = new ToolBar();
toolbarContainer.appendChild(toolbar);
btnFirst = createButton("First", "First", "First");
btnFirst.setTooltiptext(btnFirst.getTooltiptext()+" Alt+Home");
toolbar.appendChild(btnFirst);
btnPrevious = createButton("Previous", "Previous", "Previous");
btnPrevious.setTooltiptext(btnPrevious.getTooltiptext()+" Alt+Left");
toolbar.appendChild(btnPrevious);
btnRecordInfo = new ToolBarButton();
btnRecordInfo.setLabel("");
@ -147,8 +150,10 @@ public class BreadCrumb extends Div implements EventListener<Event> {
btnRecordInfo.setId("recordInfo");
toolbar.appendChild(btnRecordInfo);
btnNext = createButton("Next", "Next", "Next");
btnNext.setTooltiptext(btnNext.getTooltiptext()+" Alt+Right");
toolbar.appendChild(btnNext);
btnLast = createButton("Last", "Last", "Last");
btnLast.setTooltiptext(btnLast.getTooltiptext()+" Alt+End");
toolbar.appendChild(btnLast);
messageContainer = new Hbox();
@ -357,6 +362,29 @@ public class BreadCrumb extends Div implements EventListener<Event> {
linkPopup.detach();
linkPopup = null;
}
} else if (event.getName().equals(Events.ON_CTRL_KEY)) {
if (!LayoutUtils.isReallyVisible(this)) return;
KeyEvent keyEvent = (KeyEvent) event;
if (keyEvent.isAltKey()) {
if (keyEvent.getKeyCode() == KeyEvent.LEFT) {
if (toolbarListener != null) {
toolbarListener.onPrevious();
}
} else if (keyEvent.getKeyCode() == KeyEvent.RIGHT) {
if (toolbarListener != null) {
toolbarListener.onNext();
}
} else if (keyEvent.getKeyCode() == KeyEvent.HOME) {
if (toolbarListener != null) {
toolbarListener.onFirst();
}
} else if (keyEvent.getKeyCode() == KeyEvent.END) {
if (toolbarListener != null) {
toolbarListener.onLast();
}
}
}
} else {
Events.sendEvent(this, event);
}
@ -633,6 +661,10 @@ public class BreadCrumb extends Div implements EventListener<Event> {
super.onPageDetached(page);
if (linkPopup != null)
linkPopup.detach();
try {
SessionManager.getSessionApplication().getKeylistener().removeEventListener(Events.ON_CTRL_KEY, this);
} catch (Exception e){}
}
/**
@ -663,6 +695,14 @@ public class BreadCrumb extends Div implements EventListener<Event> {
return pInfoLogs;
}
@Override
public void onPageAttached(Page newpage, Page oldpage) {
super.onPageAttached(newpage, oldpage);
if (newpage != null) {
SessionManager.getSessionApplication().getKeylistener().addEventListener(Events.ON_CTRL_KEY, this);
}
}
class RecordLink extends A {
private static final long serialVersionUID = 3793489614175751401L;

View File

@ -41,6 +41,15 @@ public class Combobox extends org.zkoss.zul.Combobox implements IdSpace
public void setEnabled(boolean enabled)
{
this.setDisabled(!enabled);
if (!enabled) {
//ensure list is close and not on focus
if (this.getPage() != null)
{
String script = "var w=zk('#"+getUuid()+"').$(); if (w){w.close();var j=jq('#"
+getUuid()+" :focus');if(j.get(0)){j.blur();}}";
Clients.response(new AuScript(script));
}
}
}
public Comboitem appendItem(String label)

View File

@ -54,7 +54,7 @@ zkforge.KeyListener = zk.$extends(zul.Widget, {
keyDown: function(evt) {
if (!evt) evt = window.event;
var keycode = evt.keyCode, zkcode; //zkcode used to search z.ctkeys
var keycode = evt.keyCode, zkcode=''; //zkcode used to search z.ctkeys
switch (keycode) {
case 13: //ENTER
zkcode = 'K';
@ -95,19 +95,12 @@ zkforge.KeyListener = zk.$extends(zul.Widget, {
this.tabIndex = 0;
}
evt.preventDefault();
evt.stopImmediatePropagation();
evt.stop();
zAu.send(new zk.Event(zk.Widget.$(this), 'onCtrlKey', {keyCode: keycode, ctrlKey: evt.ctrlKey, shiftKey: evt.shiftKey, altKey: evt.altKey}, {toServer: true}));
// Do not send request directly, otherwise onChange events won't be fired correctly in IE
//setTimeout(function () {
// zAu.send(new zk.Event(zk.Widget.$(this), 'onCtrlKey', {keyCode: keycode, ctrlKey: evt.ctrlKey, shiftKey: evt.shiftKey, altKey: evt.altKey}, {toServer: true}), 38);
//}, 10);
evt.stop();
// Special handling for IE that Event.stop doesn't support
if (document.all && window.event && !evt.preventDefault) {
evt.keyCode = 0;
}
return false;
}
return true;