diff --git a/migration/iD11/oracle/202306290925_IDEMPIERE-5786.sql b/migration/iD11/oracle/202306290925_IDEMPIERE-5786.sql new file mode 100644 index 0000000000..324a45c458 --- /dev/null +++ b/migration/iD11/oracle/202306290925_IDEMPIERE-5786.sql @@ -0,0 +1,10 @@ +-- IDEMPIERE-5786 +SELECT register_migration_script('202306290925_IDEMPIERE-5786.sql') FROM dual; + +SET SQLBLANKLINES ON +SET DEFINE OFF + +-- Jun 29, 2023, 9:25:49 AM CEST +INSERT INTO AD_SysConfig (AD_SysConfig_ID,AD_Client_ID,AD_Org_ID,Created,Updated,CreatedBy,UpdatedBy,IsActive,Name,Value,Description,EntityType,ConfigurationLevel,AD_SysConfig_UU) VALUES (200230,0,0,TO_TIMESTAMP('2023-06-29 09:25:48','YYYY-MM-DD HH24:MI:SS'),TO_TIMESTAMP('2023-06-29 09:25:48','YYYY-MM-DD HH24:MI:SS'),100,100,'Y','USE_ESC_FOR_TAB_CLOSING','N','Y - use ESC for closing tabs; N - use Alt+X for closing tabs','D','C','a33cec55-070b-41bf-9448-26b797237ee6') +; + diff --git a/migration/iD11/postgresql/202306290925_IDEMPIERE-5786.sql b/migration/iD11/postgresql/202306290925_IDEMPIERE-5786.sql new file mode 100644 index 0000000000..435c748bcf --- /dev/null +++ b/migration/iD11/postgresql/202306290925_IDEMPIERE-5786.sql @@ -0,0 +1,7 @@ +-- IDEMPIERE-5786 +SELECT register_migration_script('202306290925_IDEMPIERE-5786.sql') FROM dual; + +-- Jun 29, 2023, 9:25:49 AM CEST +INSERT INTO AD_SysConfig (AD_SysConfig_ID,AD_Client_ID,AD_Org_ID,Created,Updated,CreatedBy,UpdatedBy,IsActive,Name,Value,Description,EntityType,ConfigurationLevel,AD_SysConfig_UU) VALUES (200230,0,0,TO_TIMESTAMP('2023-06-29 09:25:48','YYYY-MM-DD HH24:MI:SS'),TO_TIMESTAMP('2023-06-29 09:25:48','YYYY-MM-DD HH24:MI:SS'),100,100,'Y','USE_ESC_FOR_TAB_CLOSING','N','Y - use ESC for closing tabs; N - use Alt+X for closing tabs','D','C','a33cec55-070b-41bf-9448-26b797237ee6') +; + diff --git a/org.adempiere.base/src/org/compiere/model/MSysConfig.java b/org.adempiere.base/src/org/compiere/model/MSysConfig.java index f147028b9a..5540c8fda7 100644 --- a/org.adempiere.base/src/org/compiere/model/MSysConfig.java +++ b/org.adempiere.base/src/org/compiere/model/MSysConfig.java @@ -44,7 +44,7 @@ public class MSysConfig extends X_AD_SysConfig /** * */ - private static final long serialVersionUID = 1700160594551368619L; + private static final long serialVersionUID = 4924291305767860669L; public static final String AD_CHANGELOG_SAVE_UUID = "AD_CHANGELOG_SAVE_UUID"; public static final String ADDRESS_VALIDATION = "ADDRESS_VALIDATION"; @@ -182,6 +182,7 @@ public class MSysConfig extends X_AD_SysConfig public static final String TWOPACK_COMMIT_DDL = "2PACK_COMMIT_DDL"; public static final String TWOPACK_HANDLE_TRANSLATIONS = "2PACK_HANDLE_TRANSLATIONS"; public static final String USE_EMAIL_FOR_LOGIN = "USE_EMAIL_FOR_LOGIN"; + public static final String USE_ESC_FOR_TAB_CLOSING = "USE_ESC_FOR_TAB_CLOSING"; public static final String USER_LOCKING_MAX_ACCOUNT_LOCK_MINUTES = "USER_LOCKING_MAX_ACCOUNT_LOCK_MINUTES"; public static final String USER_LOCKING_MAX_INACTIVE_PERIOD_DAY = "USER_LOCKING_MAX_INACTIVE_PERIOD_DAY"; public static final String USER_LOCKING_MAX_LOGIN_ATTEMPT = "USER_LOCKING_MAX_LOGIN_ATTEMPT"; diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/acct/WAcctViewer.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/acct/WAcctViewer.java index 7a3c2a0ecd..6368bbff59 100755 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/acct/WAcctViewer.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/acct/WAcctViewer.java @@ -29,6 +29,7 @@ import org.adempiere.base.upload.IUploadService; import org.adempiere.util.Callback; import org.adempiere.webui.ClientInfo; import org.adempiere.webui.Extensions; +import org.adempiere.webui.LayoutUtils; import org.adempiere.webui.apps.AEnv; import org.adempiere.webui.component.Button; import org.adempiere.webui.component.Checkbox; @@ -50,6 +51,7 @@ import org.adempiere.webui.component.Tabs; import org.adempiere.webui.component.VerticalBox; import org.adempiere.webui.component.WListItemRenderer; import org.adempiere.webui.component.Window; +import org.adempiere.webui.desktop.IDesktop; import org.adempiere.webui.event.DialogEvents; import org.adempiere.webui.panel.InfoPanel; import org.adempiere.webui.session.SessionManager; @@ -62,6 +64,7 @@ import org.compiere.model.MAuthorizationAccount; import org.compiere.model.MColumn; import org.compiere.model.MFactAcct; import org.compiere.model.MPeriod; +import org.compiere.model.MSysConfig; import org.compiere.model.X_AD_CtxHelp; import org.compiere.model.X_C_AcctSchema_Element; import org.compiere.report.core.RModel; @@ -81,6 +84,7 @@ 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; +import org.zkoss.zk.ui.event.KeyEvent; import org.zkoss.zul.Borderlayout; import org.zkoss.zul.Caption; import org.zkoss.zul.Center; @@ -199,6 +203,10 @@ public class WAcctViewer extends Window implements EventListener private Borderlayout resultPanel; private RModel m_rmodel; + /** + * SysConfig USE_ESC_FOR_TAB_CLOSING + */ + private boolean isUseEscForTabClosing = MSysConfig.getBooleanValue(MSysConfig.USE_ESC_FOR_TAB_CLOSING, false, Env.getAD_Client_ID(Env.getCtx())); /** Logger */ private static final CLogger log = CLogger.getCLogger(WAcctViewer.class); @@ -234,6 +242,8 @@ public class WAcctViewer extends Window implements EventListener dynInit (AD_Table_ID, Record_ID); setAttribute(MODE_KEY, MODE_EMBEDDED); setAttribute(Window.INSERT_POSITION_KEY, Window.INSERT_NEXT); + setAttribute(IDesktop.WINDOWNO_ATTRIBUTE, m_windowNo); // for closing the window with shortcut + SessionManager.getSessionApplication().getKeylistener().addEventListener(Events.ON_CTRL_KEY, this); AEnv.showWindow(this); } catch(Exception e) @@ -790,6 +800,11 @@ public class WAcctViewer extends Window implements EventListener else if (Events.ON_DOUBLE_CLICK.equals(e.getName()) && source instanceof Listbox && source == table) { actionZoomFactAcct(); } + else if (e.getName().equals(Events.ON_CTRL_KEY)) { + KeyEvent keyEvent = (KeyEvent) e; + if (LayoutUtils.isReallyVisible(this)) + this.onCtrlKeyEvent(keyEvent); + } } // onEvent /** @@ -1393,4 +1408,18 @@ public class WAcctViewer extends Window implements EventListener if (newpage != null) SessionManager.getAppDesktop().updateHelpContext(X_AD_CtxHelp.CTXTYPE_Home, 0); } + + /** + * Handle shortcut key event + * @param keyEvent + */ + private void onCtrlKeyEvent(KeyEvent keyEvent) { + if ((keyEvent.isAltKey() && keyEvent.getKeyCode() == 0x58) // Alt-X + || (keyEvent.getKeyCode() == 0x1B && isUseEscForTabClosing)) { // ESC + if (m_windowNo > 0) { + keyEvent.stopPropagation(); + SessionManager.getAppDesktop().closeWindow(m_windowNo); + } + } + } } diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/ADWindowToolbar.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/ADWindowToolbar.java index 89fbb5f890..a4cf5a147b 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/ADWindowToolbar.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/ADWindowToolbar.java @@ -90,7 +90,7 @@ public class ADWindowToolbar extends ToolBar implements EventListener /** * generated serial id */ - private static final long serialVersionUID = -5151981978053022864L; + private static final long serialVersionUID = -2174135931334134570L; /** * Attribute for {@link #overflowPopup} to store the last close timestamp in ms. @@ -177,13 +177,6 @@ public class ADWindowToolbar extends ToolBar implements EventListener private boolean isAllowProductInfo = MRole.getDefault().canAccess_Info_Product(); private int windowNo = 0; - /** previous key event time in ms **/ - private long prevKeyEventTime = 0; - /** - * Previous key event. - * Use together with prevKeyEventTime to detect double fire of key event from browser - */ - private KeyEvent prevKeyEvent; /** * Maintain hierarchical Quick form by its parent-child tab while open leaf @@ -203,6 +196,10 @@ public class ADWindowToolbar extends ToolBar implements EventListener private int prevWidth; /** AD Window content part that own this toolbar **/ private AbstractADWindowContent windowContent; + /** + * SysConfig USE_ESC_FOR_TAB_CLOSING + */ + private boolean isUseEscForTabClosing = MSysConfig.getBooleanValue(MSysConfig.USE_ESC_FOR_TAB_CLOSING, false, Env.getAD_Client_ID(Env.getCtx())); /** * default constructor @@ -578,22 +575,8 @@ public class ADWindowToolbar extends ToolBar implements EventListener if (!(keyEvent.getKeyCode() == KeyEvent.F2) && windowContent != null && windowContent.getOpenQuickFormTabs().size() > 0) return; - 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(); - if (prevKeyEvent != null && prevKeyEventTime > 0 && - prevKeyEvent.getKeyCode() == keyEvent.getKeyCode() && - prevKeyEvent.getTarget() == keyEvent.getTarget() && - prevKeyEvent.isAltKey() == keyEvent.isAltKey() && - prevKeyEvent.isCtrlKey() == keyEvent.isCtrlKey() && - prevKeyEvent.isShiftKey() == keyEvent.isShiftKey()) { - if ((time - prevKeyEventTime) <= 300) { - return; - } - } - this.onCtrlKeyEvent(keyEvent); - } + if (LayoutUtils.isReallyVisible(this)) + this.onCtrlKeyEvent(keyEvent); } else if (Events.ON_SELECT.equals(eventName)) { int index = fQueryName.getSelectedIndex(); @@ -931,21 +914,18 @@ public class ADWindowToolbar extends ToolBar implements EventListener ToolBarButton btn = null; if (keyEvent.isAltKey() && !keyEvent.isCtrlKey() && !keyEvent.isShiftKey()) { - if (keyEvent.getKeyCode() == VK_X) + if ((keyEvent.getKeyCode() == VK_X)) { - if (windowNo > 0) - { - prevKeyEventTime = System.currentTimeMillis(); - prevKeyEvent = keyEvent; - keyEvent.stopPropagation(); - SessionManager.getAppDesktop().closeWindow(windowNo); - } + closeWindow(keyEvent); } else { btn = altKeyMap.get(keyEvent.getKeyCode()); } } + else if (keyEvent.getKeyCode() == 0x1B && isUseEscForTabClosing) { // ESC + closeWindow(keyEvent); + } else if (!keyEvent.isAltKey() && keyEvent.isCtrlKey() && !keyEvent.isShiftKey()) { if (keyEvent.getKeyCode() == KeyEvent.F2) @@ -980,6 +960,18 @@ public class ADWindowToolbar extends ToolBar implements EventListener fireButtonClickEvent(keyEvent, btn); } + /** + * Close Window + * @param keyEvent + */ + private void closeWindow(KeyEvent keyEvent) { + if (windowNo > 0) + { + keyEvent.stopPropagation(); + SessionManager.getAppDesktop().closeWindow(windowNo); + } + } + /** * Fire ON_Click event for button, trigger by shortcut key event. * @param keyEvent source shortcut key event @@ -988,8 +980,6 @@ public class ADWindowToolbar extends ToolBar implements EventListener private void fireButtonClickEvent(KeyEvent keyEvent, ToolBarButton btn) { if (btn != null) { - prevKeyEventTime = System.currentTimeMillis(); - prevKeyEvent = keyEvent; keyEvent.stopPropagation(); if (!btn.isDisabled() && btn.isVisible()) { Events.sendEvent(btn, new Event(Events.ON_CLICK, btn)); diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/DetailPane.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/DetailPane.java index 4a956def52..6ec39c0636 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/DetailPane.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/DetailPane.java @@ -87,11 +87,10 @@ import org.zkoss.zul.Toolbar; * @author hengsin */ public class DetailPane extends Panel implements EventListener, IdSpace { - /** * generated serial id */ - private static final long serialVersionUID = 6251897492168864784L; + private static final long serialVersionUID = 3764215603459946930L; public static final String BTN_PROCESS_ID = "BtnProcess"; @@ -130,14 +129,6 @@ public class DetailPane extends Panel implements EventListener, IdSpace { private static final String QUICK_FORM_IMAGE = "images/QuickForm16.png"; private static final String TOGGLE_IMAGE = "images/Multi16.png"; - /** Timestamp for previous key event **/ - private long prevKeyEventTime = 0; - /** - * Previous KeyEvent reference. - * Use together with {@link #prevKeyEventTime} to detect double firing of key event by browser. - */ - private KeyEvent prevKeyEvent; - /** tabbox for AD_Tabs **/ private Tabbox tabbox; @@ -800,22 +791,8 @@ public class DetailPane extends Panel implements EventListener, IdSpace { LayoutUtils.redraw(this); } else if (event.getName().equals(Events.ON_CTRL_KEY)) { KeyEvent keyEvent = (KeyEvent) event; - 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(); - if (prevKeyEvent != null && prevKeyEventTime > 0 && - prevKeyEvent.getKeyCode() == keyEvent.getKeyCode() && - prevKeyEvent.getTarget() == keyEvent.getTarget() && - prevKeyEvent.isAltKey() == keyEvent.isAltKey() && - prevKeyEvent.isCtrlKey() == keyEvent.isCtrlKey() && - prevKeyEvent.isShiftKey() == keyEvent.isShiftKey()) { - if ((time - prevKeyEventTime) <= 300) { - return; - } - } + if (LayoutUtils.isReallyVisible(this)) this.onCtrlKeyEvent(keyEvent); - } } } @@ -1147,8 +1124,6 @@ public class DetailPane extends Panel implements EventListener, IdSpace { } } if (btn != null) { - prevKeyEventTime = System.currentTimeMillis(); - prevKeyEvent = keyEvent; keyEvent.stopPropagation(); if (!btn.isDisabled() && btn.isVisible()) { Events.sendEvent(btn, new Event(Events.ON_CLICK, btn)); @@ -1164,12 +1139,11 @@ public class DetailPane extends Panel implements EventListener, IdSpace { * Custom {@link org.adempiere.webui.component.Tabpanel} implementation for DetailPane. */ public static class Tabpanel extends org.adempiere.webui.component.Tabpanel { - /** * generated serial id */ - private static final long serialVersionUID = 8248794614430375822L; - + private static final long serialVersionUID = -2502140440194514450L; + private ToolBar toolbar; private RecordToolbar recordToolBar; @@ -1357,11 +1331,11 @@ public class DetailPane extends Panel implements EventListener, IdSpace { * */ private static class RecordToolbar extends Hlayout { - /** * generated serial id */ - private static final long serialVersionUID = 5024630043211194429L; + private static final long serialVersionUID = -3369063577339438823L; + private ToolBarButton btnFirst; private ToolBarButton btnPrevious; private ToolBarButton btnRecordInfo; diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/ProcessDialog.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/ProcessDialog.java index 804dec27d2..015646c52a 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/ProcessDialog.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/ProcessDialog.java @@ -43,6 +43,7 @@ import org.adempiere.webui.util.ZKUpdateUtil; import org.adempiere.webui.window.Dialog; import org.adempiere.webui.window.SimplePDFViewer; import org.compiere.model.MProcess; +import org.compiere.model.MSysConfig; import org.compiere.model.X_AD_CtxHelp; import org.compiere.print.ReportEngine; import org.compiere.process.ProcessInfo; @@ -124,12 +125,10 @@ public class ProcessDialog extends AbstractProcessDialog implements EventListene /** Window No */ private int m_WindowNo = -1; - /** timestamp of previous key event **/ - private long prevKeyEventTime = 0; /** - * Previous key event. use together with {@link #prevKeyEventTime} to detect double firing of key event from browser. + * SysConfig USE_ESC_FOR_TAB_CLOSING */ - private KeyEvent prevKeyEvent; + private boolean isUseEscForTabClosing = MSysConfig.getBooleanValue(MSysConfig.USE_ESC_FOR_TAB_CLOSING, false, Env.getAD_Client_ID(Env.getCtx())); /** * Dialog to start a process/report @@ -236,22 +235,8 @@ public class ProcessDialog extends AbstractProcessDialog implements EventListene } } else if (event.getName().equals(Events.ON_CTRL_KEY)) { KeyEvent keyEvent = (KeyEvent) event; - 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(); - if (prevKeyEvent != null && prevKeyEventTime > 0 && - prevKeyEvent.getKeyCode() == keyEvent.getKeyCode() && - prevKeyEvent.getTarget() == keyEvent.getTarget() && - prevKeyEvent.isAltKey() == keyEvent.isAltKey() && - prevKeyEvent.isCtrlKey() == keyEvent.isCtrlKey() && - prevKeyEvent.isShiftKey() == keyEvent.isShiftKey()) { - if ((time - prevKeyEventTime) <= 300) { - return; - } - } + if (LayoutUtils.isReallyVisible(this)) this.onCtrlKeyEvent(keyEvent); - } } else { super.onEvent(event); } @@ -279,10 +264,9 @@ public class ProcessDialog extends AbstractProcessDialog implements EventListene * @param keyEvent */ private void onCtrlKeyEvent(KeyEvent keyEvent) { - if (keyEvent.isAltKey() && keyEvent.getKeyCode() == 0x58) { // Alt-X + if ((keyEvent.isAltKey() && keyEvent.getKeyCode() == 0x58) // Alt-X + || (keyEvent.getKeyCode() == 0x1B && isUseEscForTabClosing)) { // ESC if (m_WindowNo > 0) { - prevKeyEventTime = System.currentTimeMillis(); - prevKeyEvent = keyEvent; keyEvent.stopPropagation(); SessionManager.getAppDesktop().closeWindow(m_WindowNo); } diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/form/WBOMDrop.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/form/WBOMDrop.java index 2768d0358e..59956d3285 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/form/WBOMDrop.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/form/WBOMDrop.java @@ -678,6 +678,8 @@ public class WBOMDrop extends ADForm implements EventListener, ValueChang @Override public void onEvent (Event e) throws Exception { + super.onEvent(e); + if (log.isLoggable(Level.CONFIG)) log.config(e.getName()); Object source = e.getTarget(); diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/form/WPluginManager.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/form/WPluginManager.java index 6552295f40..e23ce35994 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/form/WPluginManager.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/form/WPluginManager.java @@ -323,6 +323,8 @@ public class WPluginManager extends ADForm implements EventListener { @Override public void onEvent(Event event) throws Exception { + super.onEvent(event); + if (Events.ON_SELECT.equals(event.getName()) && event.getTarget() == pluginsTable) refreshActionList(); else if (Events.ON_CLICK.equals(event.getName()) && event.getTarget() == pluginProcess) diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/wf/WFEditor.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/wf/WFEditor.java index 1e55ab52f5..642e404d24 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/wf/WFEditor.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/wf/WFEditor.java @@ -177,6 +177,8 @@ public class WFEditor extends ADForm { @Override public void onEvent(Event event) throws Exception { + super.onEvent(event); + if (event.getTarget().getId().equals(ConfirmPanel.A_CANCEL)) this.detach(); else if (event.getTarget().getId().equals(ConfirmPanel.A_OK)) diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/wf/WFPanel.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/wf/WFPanel.java index 048e340215..9cff5d4387 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/wf/WFPanel.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/wf/WFPanel.java @@ -19,12 +19,15 @@ import java.util.ArrayList; import java.util.List; import java.util.logging.Level; +import org.adempiere.webui.LayoutUtils; +import org.adempiere.webui.desktop.IDesktop; import org.adempiere.webui.panel.IHelpContext; import org.adempiere.webui.part.WindowContainer; import org.adempiere.webui.session.SessionManager; import org.adempiere.webui.util.ZKUpdateUtil; import org.compiere.apps.wf.WFGraphLayout; import org.compiere.apps.wf.WFNodeWidget; +import org.compiere.model.MSysConfig; import org.compiere.model.X_AD_CtxHelp; import org.compiere.util.CLogger; import org.compiere.util.Env; @@ -37,11 +40,12 @@ import org.zkoss.zhtml.Tr; import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.event.EventListener; import org.zkoss.zk.ui.event.Events; +import org.zkoss.zk.ui.event.KeyEvent; import org.zkoss.zul.Borderlayout; import org.zkoss.zul.Center; -import org.zkoss.zul.South; import org.zkoss.zul.Div; import org.zkoss.zul.Html; +import org.zkoss.zul.South; /** * WorkFlow Panel @@ -53,9 +57,13 @@ public class WFPanel extends Borderlayout implements EventListener, IHelp /** * */ - private static final long serialVersionUID = 8777798080154603970L; - + private static final long serialVersionUID = 3748544216557474367L; + /** + * SysConfig USE_ESC_FOR_TAB_CLOSING + */ + private boolean isUseEscForTabClosing = MSysConfig.getBooleanValue(MSysConfig.USE_ESC_FOR_TAB_CLOSING, false, Env.getAD_Client_ID(Env.getCtx())); + /** * Create Workflow Panel */ @@ -71,6 +79,8 @@ public class WFPanel extends Borderlayout implements EventListener, IHelp log.log(Level.SEVERE, "WFPanel", e); } m_WindowNo = SessionManager.getAppDesktop().registerWindow(this); + setAttribute(IDesktop.WINDOWNO_ATTRIBUTE, m_WindowNo); // for closing the window with shortcut + SessionManager.getSessionApplication().getKeylistener().addEventListener(Events.ON_CTRL_KEY, this); } // WFPanel /** Window No */ @@ -274,8 +284,14 @@ public class WFPanel extends Borderlayout implements EventListener, IHelp } } } - else if (event.getName().equals(WindowContainer.ON_WINDOW_CONTAINER_SELECTION_CHANGED_EVENT)) + else if (event.getName().equals(WindowContainer.ON_WINDOW_CONTAINER_SELECTION_CHANGED_EVENT)) { SessionManager.getAppDesktop().updateHelpContext(X_AD_CtxHelp.CTXTYPE_Workflow, m_wf.getAD_Workflow_ID()); + } + else if (event.getName().equals(Events.ON_CTRL_KEY)) { + KeyEvent keyEvent = (KeyEvent) event; + if (LayoutUtils.isReallyVisible(this)) + this.onCtrlKeyEvent(keyEvent); + } } private void start(MWFNode wfn) { @@ -295,4 +311,17 @@ public class WFPanel extends Borderlayout implements EventListener, IHelp } } + /** + * Handle shortcut key event + * @param keyEvent + */ + private void onCtrlKeyEvent(KeyEvent keyEvent) { + if ((keyEvent.isAltKey() && keyEvent.getKeyCode() == 0x58) // Alt-X + || (keyEvent.getKeyCode() == 0x1B && isUseEscForTabClosing)) { // ESC + if (m_WindowNo > 0) { + keyEvent.stopPropagation(); + SessionManager.getAppDesktop().closeWindow(m_WindowNo); + } + } + } } // WFPanel diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/ADForm.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/ADForm.java index 89d567dad4..3505f1efc0 100755 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/ADForm.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/ADForm.java @@ -20,19 +20,24 @@ package org.adempiere.webui.panel; import java.util.logging.Level; import org.adempiere.webui.Extensions; +import org.adempiere.webui.LayoutUtils; import org.adempiere.webui.component.Window; +import org.adempiere.webui.desktop.IDesktop; import org.adempiere.webui.exception.ApplicationException; import org.adempiere.webui.part.WindowContainer; import org.adempiere.webui.session.SessionManager; import org.adempiere.webui.util.ZKUpdateUtil; import org.compiere.model.GridTab; import org.compiere.model.MForm; +import org.compiere.model.MSysConfig; import org.compiere.model.X_AD_CtxHelp; import org.compiere.process.ProcessInfo; import org.compiere.util.CLogger; import org.compiere.util.Env; import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.event.EventListener; +import org.zkoss.zk.ui.event.Events; +import org.zkoss.zk.ui.event.KeyEvent; /** * Adempiere Web UI custom form. @@ -45,7 +50,7 @@ public abstract class ADForm extends Window implements EventListener, IHe /** * */ - private static final long serialVersionUID = -2238655179806815227L; + private static final long serialVersionUID = -5381283117636286759L; /** The class' logging enabler */ protected static final CLogger logger; @@ -68,6 +73,11 @@ public abstract class ADForm extends Window implements EventListener, IHe private IFormController m_customForm; + /** + * SysConfig USE_ESC_FOR_TAB_CLOSING + */ + private boolean isUseEscForTabClosing = MSysConfig.getBooleanValue(MSysConfig.USE_ESC_FOR_TAB_CLOSING, false, Env.getAD_Client_ID(Env.getCtx())); + /** * Constructor */ @@ -203,6 +213,8 @@ public abstract class ADForm extends Window implements EventListener, IHe Env.setPredefinedVariables(Env.getCtx(), form.getWindowNo(), predefinedContextVariables); Env.setContext(Env.getCtx(), form.getWindowNo(), "IsSOTrx", isSOTrx); form.init(adFormID, name); + form.setAttribute(IDesktop.WINDOWNO_ATTRIBUTE, form.getWindowNo()); // for closing the window with shortcut + SessionManager.getSessionApplication().getKeylistener().addEventListener(Events.ON_CTRL_KEY, form); return form; } else @@ -220,6 +232,11 @@ public abstract class ADForm extends Window implements EventListener, IHe if (event.getName().equals(WindowContainer.ON_WINDOW_CONTAINER_SELECTION_CHANGED_EVENT)) { SessionManager.getAppDesktop().updateHelpContext(X_AD_CtxHelp.CTXTYPE_Form, getAdFormId()); } + else if (event.getName().equals(Events.ON_CTRL_KEY)) { + KeyEvent keyEvent = (KeyEvent) event; + if (LayoutUtils.isReallyVisible(this)) + this.onCtrlKeyEvent(keyEvent); + } } /** @@ -261,4 +278,18 @@ public abstract class ADForm extends Window implements EventListener, IHe { return gridTab; } + + /** + * Handle shortcut key event + * @param keyEvent + */ + private void onCtrlKeyEvent(KeyEvent keyEvent) { + if ((keyEvent.isAltKey() && keyEvent.getKeyCode() == 0x58) // Alt-X + || (keyEvent.getKeyCode() == 0x1B && isUseEscForTabClosing)) { // ESC + if (m_WindowNo > 0) { + keyEvent.stopPropagation(); + SessionManager.getAppDesktop().closeWindow(m_WindowNo); + } + } + } } diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/InfoPanel.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/InfoPanel.java index 30d35a680b..eb43bded87 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/InfoPanel.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/InfoPanel.java @@ -57,6 +57,7 @@ import org.adempiere.webui.component.ProcessInfoDialog; import org.adempiere.webui.component.WListItemRenderer; import org.adempiere.webui.component.WListbox; import org.adempiere.webui.component.Window; +import org.adempiere.webui.desktop.IDesktop; import org.adempiere.webui.editor.WEditor; import org.adempiere.webui.event.DialogEvents; import org.adempiere.webui.event.ValueChangeEvent; @@ -136,7 +137,7 @@ public abstract class InfoPanel extends Window implements EventListener, /** * */ - private static final long serialVersionUID = -3055980415629613992L; + private static final long serialVersionUID = 8253708190979803268L; protected static final String ON_USER_QUERY_ATTR = "ON_USER_QUERY"; protected static final String INFO_QUERY_TIME_OUT_ERROR = "InfoQueryTimeOutError"; @@ -340,7 +341,8 @@ public abstract class InfoPanel extends Window implements EventListener, addEventListener(ON_RUN_PROCESS, this); addEventListener(ON_SELECT_ALL_RECORDS, this); addEventListener(Events.ON_CLOSE, this); - addEventListener(Events.ON_CANCEL, e -> onCancel()); + + setAttribute(IDesktop.WINDOWNO_ATTRIBUTE, p_WindowNo); // for closing the window with shortcut } // InfoPanel /** @@ -605,6 +607,12 @@ public abstract class InfoPanel extends Window implements EventListener, protected Button btCbbProcess; protected Combobox cbbProcess; protected Button btMenuProcess; + + /** + * SysConfig USE_ESC_FOR_TAB_CLOSING + */ + private boolean isUseEscForTabClosing = MSysConfig.getBooleanValue(MSysConfig.USE_ESC_FOR_TAB_CLOSING, false, Env.getAD_Client_ID(Env.getCtx())); + /** * Loaded correctly * @return true if loaded OK @@ -2378,9 +2386,8 @@ public abstract class InfoPanel extends Window implements EventListener, else if (event.getName().equals(Events.ON_CTRL_KEY)) { KeyEvent keyEvent = (KeyEvent) event; - if (LayoutUtils.isReallyVisible(this)) { + if (LayoutUtils.isReallyVisible(this)) this.onCtrlKeyEvent(keyEvent); - } }else if (event.getName().equals(Events.ON_OK)){// on ok when focus at non parameter component. example grid result if (m_lookup && contentPanel.getSelectedIndex() >= 0){ // do nothing when parameter not change and at window mode, or at dialog mode but select non record @@ -2420,6 +2427,12 @@ public abstract class InfoPanel extends Window implements EventListener, } } else if (keyEvent.getKeyCode() == VK_ENTER) { // Enter // do nothing, let on_ok at infoWindo do, at this is too soon to get value from control, it's not bind + } else if ((keyEvent.isAltKey() && keyEvent.getKeyCode() == 0x58) // Alt-X + || (keyEvent.getKeyCode() == 0x1B && isUseEscForTabClosing)) { // ESC + if (p_WindowNo > 0) { + keyEvent.stopPropagation(); + SessionManager.getAppDesktop().closeWindow(p_WindowNo); + } } } diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/part/WindowContainer.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/part/WindowContainer.java index 5cebdfc278..bd46e3d801 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/part/WindowContainer.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/part/WindowContainer.java @@ -458,7 +458,7 @@ public class WindowContainer extends AbstractUIPart implements EventListener { + /** + * + */ + private static final long serialVersionUID = 3349721592479638482L; + /** * @param mAssignment optional assignment * @param createNew if true, allows to create new assignments */ - private static final long serialVersionUID = -5948901371276429661L; private Callback m_callback; private Component m_parent; + /** Window No */ + private int m_windowNo; + + /** + * SysConfig USE_ESC_FOR_TAB_CLOSING + */ + private boolean isUseEscForTabClosing = MSysConfig.getBooleanValue(MSysConfig.USE_ESC_FOR_TAB_CLOSING, false, Env.getAD_Client_ID(Env.getCtx())); /** * Constructor @@ -160,6 +174,11 @@ public class InfoSchedule extends Window implements EventListener log.log(Level.SEVERE, "InfoSchedule", ex); } displayCalendar(); + + m_windowNo = SessionManager.getAppDesktop().registerWindow(this); + setAttribute(IDesktop.WINDOWNO_ATTRIBUTE, m_windowNo); // for closing the window with shortcut + SessionManager.getSessionApplication().getKeylistener().addEventListener(Events.ON_CTRL_KEY, this); + } // InfoSchedule /** @@ -480,6 +499,11 @@ public class InfoSchedule extends Window implements EventListener doEdit((CalendarsEvent)event); else if (event.getTarget() == fieldResource) displayCalendar(); + else if (event.getName().equals(Events.ON_CTRL_KEY)) { + KeyEvent keyEvent = (KeyEvent) event; + if (LayoutUtils.isReallyVisible(this)) + this.onCtrlKeyEvent(keyEvent); + } // } @@ -660,4 +684,18 @@ public class InfoSchedule extends Window implements EventListener mask.detach(); } } + + /** + * Handle shortcut key event + * @param keyEvent + */ + private void onCtrlKeyEvent(KeyEvent keyEvent) { + if ((keyEvent.isAltKey() && keyEvent.getKeyCode() == 0x58) // Alt-X + || (keyEvent.getKeyCode() == 0x1B && isUseEscForTabClosing)) { // ESC + if (m_windowNo > 0) { + keyEvent.stopPropagation(); + SessionManager.getAppDesktop().closeWindow(m_windowNo); + } + } + } } // InfoSchedule diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/ZkJRViewer.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/ZkJRViewer.java index 4004df1383..64c273a151 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/ZkJRViewer.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/ZkJRViewer.java @@ -93,7 +93,7 @@ public class ZkJRViewer extends Window implements EventListener, ITabOnCl /** * */ - private static final long serialVersionUID = -7204858572267608018L; + private static final long serialVersionUID = -8782402996207677811L; private JasperPrint jasperPrint; private java.util.List jasperPrintList; @@ -109,8 +109,6 @@ public class ZkJRViewer extends Window implements EventListener, ITabOnCl /** Window No */ private int m_WindowNo = -1; - private long prevKeyEventTime = 0; - private KeyEvent prevKeyEvent; private String m_title; // local title - embedded windows clear the title Toolbar toolbar = new Toolbar(); @@ -130,6 +128,10 @@ public class ZkJRViewer extends Window implements EventListener, ITabOnCl protected final Map> mediaSuppliers = new HashMap>(); protected Map uploadServicesMap = new HashMap<>(); + /** + * SysConfig USE_ESC_FOR_TAB_CLOSING + */ + private boolean isUseEscForTabClosing = MSysConfig.getBooleanValue(MSysConfig.USE_ESC_FOR_TAB_CLOSING, false, Env.getAD_Client_ID(Env.getCtx())); private final ExportFormat[] exportFormats = new ExportFormat[] { new ExportFormat(PDF_FILE_EXT + " - " + Msg.getMsg(Env.getCtx(), "FilePDF"), PDF_FILE_EXT, PDF_MIME_TYPE), @@ -654,30 +656,15 @@ public class ZkJRViewer extends Window implements EventListener, ITabOnCl actionPerformed(event); } else if (event.getName().equals(Events.ON_CTRL_KEY)) { KeyEvent keyEvent = (KeyEvent) event; - 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(); - if (prevKeyEvent != null && prevKeyEventTime > 0 && - prevKeyEvent.getKeyCode() == keyEvent.getKeyCode() && - prevKeyEvent.getTarget() == keyEvent.getTarget() && - prevKeyEvent.isAltKey() == keyEvent.isAltKey() && - prevKeyEvent.isCtrlKey() == keyEvent.isCtrlKey() && - prevKeyEvent.isShiftKey() == keyEvent.isShiftKey()) { - if ((time - prevKeyEventTime) <= 300) { - return; - } - } + if (LayoutUtils.isReallyVisible(this)) this.onCtrlKeyEvent(keyEvent); - } } } private void onCtrlKeyEvent(KeyEvent keyEvent) { - if (keyEvent.isAltKey() && keyEvent.getKeyCode() == 0x58) { // Alt-X + if ((keyEvent.isAltKey() && keyEvent.getKeyCode() == 0x58) // Alt-X + || (keyEvent.getKeyCode() == 0x1B && isUseEscForTabClosing)) { // ESC if (m_WindowNo > 0) { - prevKeyEventTime = System.currentTimeMillis(); - prevKeyEvent = keyEvent; keyEvent.stopPropagation(); SessionManager.getAppDesktop().closeWindow(m_WindowNo); } diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/ZkReportViewer.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/ZkReportViewer.java index 498fdd19b1..d514e7ae40 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/ZkReportViewer.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/ZkReportViewer.java @@ -149,12 +149,11 @@ import org.zkoss.zul.impl.XulElement; * @author Low Heng Sin */ public class ZkReportViewer extends Window implements EventListener, IReportViewerExportSource { - /** - * generated serial id + * */ - private static final long serialVersionUID = 6307014622485159910L; - + private static final long serialVersionUID = 3732290698059632847L; + protected static final String CSV_OUTPUT_TYPE = "CSV"; protected static final String HTML_OUTPUT_TYPE = "HTML"; protected static final String PDF_OUTPUT_TYPE = "PDF"; @@ -163,8 +162,6 @@ public class ZkReportViewer extends Window implements EventListener, IRep /** Window No */ protected int m_WindowNo = -1; - private long prevKeyEventTime = 0; - private KeyEvent prevKeyEvent; /** Print Context */ private Properties m_ctx; /** Setting Values */ @@ -242,6 +239,11 @@ public class ZkReportViewer extends Window implements EventListener, IRep private Center center; private FindWindow find; + /** + * SysConfig USE_ESC_FOR_TAB_CLOSING + */ + private boolean isUseEscForTabClosing = MSysConfig.getBooleanValue(MSysConfig.USE_ESC_FOR_TAB_CLOSING, false, Env.getAD_Client_ID(Env.getCtx())); + /** * Static Layout * @throws Exception @@ -1158,22 +1160,8 @@ public class ZkReportViewer extends Window implements EventListener, IRep onRenderReportEvent(); } else if (event.getName().equals(Events.ON_CTRL_KEY)) { KeyEvent keyEvent = (KeyEvent) event; - 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(); - if (prevKeyEvent != null && prevKeyEventTime > 0 && - prevKeyEvent.getKeyCode() == keyEvent.getKeyCode() && - prevKeyEvent.getTarget() == keyEvent.getTarget() && - prevKeyEvent.isAltKey() == keyEvent.isAltKey() && - prevKeyEvent.isCtrlKey() == keyEvent.isCtrlKey() && - prevKeyEvent.isShiftKey() == keyEvent.isShiftKey()) { - if ((time - prevKeyEventTime) <= 300) { - return; - } - } + if (LayoutUtils.isReallyVisible(this)) this.onCtrlKeyEvent(keyEvent); - } } else if (event.getTarget() instanceof ProcessModalDialog) { @@ -1201,10 +1189,9 @@ public class ZkReportViewer extends Window implements EventListener, IRep } private void onCtrlKeyEvent(KeyEvent keyEvent) { - if (keyEvent.isAltKey() && keyEvent.getKeyCode() == 0x58) { // Alt-X + if ((keyEvent.isAltKey() && keyEvent.getKeyCode() == 0x58) // Alt-X + || (keyEvent.getKeyCode() == 0x1B && isUseEscForTabClosing)) { // ESC if (m_WindowNo > 0) { - prevKeyEventTime = System.currentTimeMillis(); - prevKeyEvent = keyEvent; keyEvent.stopPropagation(); SessionManager.getAppDesktop().closeWindow(m_WindowNo); }