IDEMPIERE-5786 - Refactor ESC/Alt+X Shortcut for Closing Tabs (#1917)

* IDEMPIERE-5786 - ESC Shortcut for Closing Tabs

- remove duplicate registering of on_cancel event on InfoPanel
- register on_cancel event on WindowContainer

* IDEMPIERE-5786 - partially revert ESC Shortcut for Closing Tabs

* IDEMPIERE-5786 - improve closing tabs with shortcut

- info windows
- forms
- workflows
- find window

* IDEMPIERE-5786 - SysConfig to Use Esc For Tab Closing

* IDEMPIERE-5786 - fix MSysConfig order

* IDEMPIERE-5786 - requested changes by Carlos

- implement shortcut on missing forms
- allow Alt+X shortcut also when ESC is allowed with the SysConfig

* IDEMPIERE-5786 - PR1917pr patch by Carlos

- removed unnecessary fix for an old firefox issue
This commit is contained in:
Peter Takács 2023-06-30 11:08:38 +02:00 committed by GitHub
parent d42aec9b39
commit f79dd5f22f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 231 additions and 145 deletions

View File

@ -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')
;

View File

@ -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')
;

View File

@ -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";

View File

@ -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<Event>
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<Event>
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<Event>
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<Event>
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);
}
}
}
}

View File

@ -90,7 +90,7 @@ public class ADWindowToolbar extends ToolBar implements EventListener<Event>
/**
* 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<Event>
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<Event>
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<Event>
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<Event>
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<Event>
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<Event>
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));

View File

@ -87,11 +87,10 @@ import org.zkoss.zul.Toolbar;
* @author hengsin
*/
public class DetailPane extends Panel implements EventListener<Event>, 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<Event>, 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<Event>, 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<Event>, 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<Event>, 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<Event>, 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;

View File

@ -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);
}

View File

@ -678,6 +678,8 @@ public class WBOMDrop extends ADForm implements EventListener<Event>, 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();

View File

@ -323,6 +323,8 @@ public class WPluginManager extends ADForm implements EventListener<Event> {
@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)

View File

@ -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))

View File

@ -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<Event>, 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<Event>, 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<Event>, 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<Event>, 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

View File

@ -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<Event>, 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<Event>, 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<Event>, 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<Event>, 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<Event>, 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);
}
}
}
}

View File

@ -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<Event>,
/**
*
*/
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<Event>,
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<Event>,
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<Event>,
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<Event>,
}
} 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);
}
}
}

View File

@ -458,7 +458,7 @@ public class WindowContainer extends AbstractUIPart implements EventListener<Eve
ZKUpdateUtil.setVflex(tabpanel, "1");
ZKUpdateUtil.setHflex(tabpanel, "1");
tabpanel.setSclass("desktop-tabpanel");
if (refTab == null)
{
tabbox.getTabs().appendChild(tab);

View File

@ -33,6 +33,7 @@ import org.adempiere.webui.component.Listbox;
import org.adempiere.webui.component.Mask;
import org.adempiere.webui.component.Window;
import org.adempiere.webui.component.ZkCssHelper;
import org.adempiere.webui.desktop.IDesktop;
import org.adempiere.webui.event.DialogEvents;
import org.adempiere.webui.panel.WSchedule;
import org.adempiere.webui.session.SessionManager;
@ -40,6 +41,7 @@ import org.adempiere.webui.util.ZKUpdateUtil;
import org.compiere.model.MAssignmentSlot;
import org.compiere.model.MResourceAssignment;
import org.compiere.model.MRole;
import org.compiere.model.MSysConfig;
import org.compiere.model.ScheduleUtil;
import org.compiere.model.X_AD_CtxHelp;
import org.compiere.util.CLogger;
@ -55,6 +57,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.Div;
import org.zkoss.zul.Hlayout;
import org.zkoss.zul.Space;
@ -76,13 +79,24 @@ import org.zkoss.zul.Vbox;
*/
public class InfoSchedule extends Window implements EventListener<Event>
{
/**
*
*/
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<MResourceAssignment> 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<Event>
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<Event>
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<Event>
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

View File

@ -93,7 +93,7 @@ public class ZkJRViewer extends Window implements EventListener<Event>, ITabOnCl
/**
*
*/
private static final long serialVersionUID = -7204858572267608018L;
private static final long serialVersionUID = -8782402996207677811L;
private JasperPrint jasperPrint;
private java.util.List<JasperPrint> jasperPrintList;
@ -109,8 +109,6 @@ public class ZkJRViewer extends Window implements EventListener<Event>, 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<Event>, ITabOnCl
protected final Map<String, Supplier<AMedia>> mediaSuppliers = new HashMap<String, Supplier<AMedia>>();
protected Map<MAuthorizationAccount, IUploadService> 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<Event>, 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);
}

View File

@ -149,12 +149,11 @@ import org.zkoss.zul.impl.XulElement;
* @author Low Heng Sin
*/
public class ZkReportViewer extends Window implements EventListener<Event>, 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<Event>, 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<Event>, 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<Event>, 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<Event>, 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);
}