IDEMPIERE-4705 Add grid toggle button to Detail Pane (#594)

This commit is contained in:
hengsin 2021-02-19 02:38:46 +08:00 committed by GitHub
parent 4ebf81b1d2
commit b1d3f9c8fd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 577 additions and 72 deletions

View File

@ -0,0 +1,10 @@
SET SQLBLANKLINES ON
SET DEFINE OFF
-- Feb 16, 2021, 5:14:50 PM MYT
INSERT INTO AD_ToolBarButton (AD_Client_ID,AD_Org_ID,Created,CreatedBy,ComponentName,IsActive,AD_ToolBarButton_ID,Name,Updated,UpdatedBy,IsCustomization,KeyStroke_KeyCode,KeyStroke_Modifiers,AD_ToolBarButton_UU,Action,SeqNo,IsAdvancedButton,IsAddSeparator,EntityType,IsShowMore) VALUES (0,0,TO_DATE('2021-02-16 17:14:49','YYYY-MM-DD HH24:MI:SS'),100,'Toggle','Y',200112,'Detail - Multi',TO_DATE('2021-02-16 17:14:49','YYYY-MM-DD HH24:MI:SS'),100,'N',0,0,'2245209c-d9eb-4948-b622-4834281bc244','D',90,'N','N','D','N')
;
SELECT register_migration_script('202102180540_IDEMPIERE-4705.sql') FROM dual
;

View File

@ -0,0 +1,7 @@
-- Feb 16, 2021, 5:14:50 PM MYT
INSERT INTO AD_ToolBarButton (AD_Client_ID,AD_Org_ID,Created,CreatedBy,ComponentName,IsActive,AD_ToolBarButton_ID,Name,Updated,UpdatedBy,IsCustomization,KeyStroke_KeyCode,KeyStroke_Modifiers,AD_ToolBarButton_UU,"action",SeqNo,IsAdvancedButton,IsAddSeparator,EntityType,IsShowMore) VALUES (0,0,TO_TIMESTAMP('2021-02-16 17:14:49','YYYY-MM-DD HH24:MI:SS'),100,'Toggle','Y',200112,'Detail - Multi',TO_TIMESTAMP('2021-02-16 17:14:49','YYYY-MM-DD HH24:MI:SS'),100,'N',0,0,'2245209c-d9eb-4948-b622-4834281bc244','D',90,'N','N','D','N')
;
SELECT register_migration_script('202102180540_IDEMPIERE-4705.sql') FROM dual
;

View File

@ -2403,7 +2403,11 @@ public class GridTab implements DataStatusListener, Evaluatee, Serializable
// log.fine("fini - " + e.toString());
} // fireDataStatusChanged
private void updateDataStatusEventProperties(DataStatusEvent e) {
/**
* update {@link DataStatusEvent} properties from gridTab
* @param e
*/
public void updateDataStatusEventProperties(DataStatusEvent e) {
e.Created = (Timestamp)getValue("Created");
e.CreatedBy = (Integer)getValue("CreatedBy");
e.Updated = (Timestamp)getValue("Updated");

View File

@ -1387,7 +1387,11 @@ DataStatusListener, IADTabpanel, IdSpace, IFieldEditorContainer
tabPanel.getGridView().invalidateGridView();
}
if (!tabPanel.isGridView()) {
tabPanel.switchRowPresentation();
if (detailPane.getSelectedPanel().isToggleToFormView()) {
detailPane.getSelectedPanel().afterToggle();
} else {
tabPanel.switchRowPresentation();
}
}
}
}
@ -1932,6 +1936,7 @@ DataStatusListener, IADTabpanel, IdSpace, IFieldEditorContainer
*
* @return true if the detailpane is visible
*/
@Override
public boolean isDetailVisible() {
if (formContainer.getSouth() == null || !formContainer.getSouth().isVisible()
|| !formContainer.getSouth().isOpen()) {

View File

@ -24,6 +24,7 @@ import java.util.LinkedHashMap;
import java.util.List;
import org.adempiere.util.Callback;
import org.adempiere.webui.adwindow.DetailPane.Tabpanel;
import org.adempiere.webui.component.ADTabListModel;
import org.adempiere.webui.component.ADTabListModel.ADTabLabel;
import org.adempiere.webui.util.ZKUpdateUtil;
@ -123,20 +124,34 @@ public class CompositeADTabbox extends AbstractADTabbox
public void onCallback(Boolean result) {
if (result) {
if (getSelectedDetailADTabpanel().getGridTab().isSingleRow()) {
onEditDetail(row, true);
if (!adWindowPanel.getActiveGridTab().isNew())
adWindowPanel.onNew();
if (headerTab.isDetailVisible() && headerTab.getDetailPane().getSelectedPanel().isToggleToFormView()) {
if (!getSelectedDetailADTabpanel().getGridTab().isNew()) {
getSelectedDetailADTabpanel().getGridTab().dataNew(false);
getSelectedDetailADTabpanel().dynamicDisplay(0);
focusToTabpanel(getSelectedDetailADTabpanel());
}
} else {
onEditDetail(row, true);
if (!adWindowPanel.getActiveGridTab().isNew())
adWindowPanel.onNew();
}
} else {
if (!getSelectedDetailADTabpanel().getGridTab().isNew()) {
getSelectedDetailADTabpanel().getGridTab().dataNew(false);
if (!((ADTabpanel)headerTab).isDetailVisible()) {
if (!headerTab.isDetailVisible()) {
String uuid = headerTab.getDetailPane().getParent().getUuid();
String vid = getSelectedDetailADTabpanel().getGridView().getUuid();
String script = "setTimeout(function(){zk('#"+uuid+"').$().setOpen(true);setTimeout(function(){var v=zk('#" + vid
+ "').$();var e=new zk.Event(v,'onEditCurrentRow',null,{toServer:true});zAu.send(e);},200);},200)";
Clients.response(new AuScript(script));
} else {
getSelectedDetailADTabpanel().getGridView().onEditCurrentRow();
boolean isFormView = headerTab.getDetailPane().getSelectedPanel().isToggleToFormView();
if (isFormView) {
getSelectedDetailADTabpanel().dynamicDisplay(0);
focusToTabpanel(getSelectedDetailADTabpanel());
} else {
getSelectedDetailADTabpanel().getGridView().onEditCurrentRow();
}
}
}
}
@ -178,6 +193,27 @@ public class CompositeADTabbox extends AbstractADTabbox
}
});
}
else if (DetailPane.ON_RECORD_NAVIGATE_EVENT.equals(event.getName())) {
final String action = (String) event.getData();
adWindowPanel.saveAndNavigate(new Callback <Boolean>() {
@Override
public void onCallback(Boolean result)
{
if (result)
{
if ("first".equalsIgnoreCase(action)) {
getSelectedDetailADTabpanel().getGridTab().navigate(0);
} else if ("previous".equalsIgnoreCase(action)) {
getSelectedDetailADTabpanel().getGridTab().navigateRelative(-1);
} else if ("next".equalsIgnoreCase(action)) {
getSelectedDetailADTabpanel().getGridTab().navigateRelative(1);
} else if ("last".equalsIgnoreCase(action)) {
getSelectedDetailADTabpanel().getGridTab().navigate(getSelectedDetailADTabpanel().getGridTab().getRowCount()-1);
}
}
}
});
}
}
private void onDelete() {
@ -242,6 +278,13 @@ public class CompositeADTabbox extends AbstractADTabbox
return detailPane;
}
private void focusToTabpanel(IADTabpanel adTabPanel ) {
if (adTabPanel != null && adTabPanel instanceof HtmlBasedComponent) {
final HtmlBasedComponent comp = (HtmlBasedComponent) adTabPanel;
Executions.schedule(layout.getDesktop(), e -> {comp.focus();}, new Event("onFocusDefer"));
}
}
protected void onEditDetail(int row, boolean formView) {
int oldIndex = selectedIndex;
@ -604,13 +647,25 @@ public class CompositeADTabbox extends AbstractADTabbox
detailPane.setSelectedIndex(0);
activateDetailIfVisible();
} else {
if (((ADTabpanel) headerTab).isDetailVisible() && detailPane.getSelectedADTabpanel() != null) {
if (headerTab.isDetailVisible() && detailPane.getSelectedADTabpanel() != null) {
IADTabpanel selectDetailPanel = detailPane.getSelectedADTabpanel();
if (!selectDetailPanel.isVisible()) {
if (!selectDetailPanel.isVisible()) {
selectDetailPanel.setVisible(true);
}
if (!selectDetailPanel.isGridView()) {
selectDetailPanel.switchRowPresentation();
boolean switchToGrid = true;
Component parent = selectDetailPanel.getParent();
while (parent != null) {
if (parent instanceof DetailPane.Tabpanel) {
DetailPane.Tabpanel dtp = (Tabpanel) parent;
switchToGrid = !dtp.isToggleToFormView();
dtp.afterToggle();
break;
}
parent = parent.getParent();
}
if (switchToGrid)
selectDetailPanel.switchRowPresentation();
}
if (selectDetailPanel instanceof ADTabpanel)
{
@ -948,8 +1003,25 @@ public class CompositeADTabbox extends AbstractADTabbox
if (row != null)
gtr.setCurrentRow(row);
}
if (wasForm && tabPanel.getTabLevel() == 0 && headerTab.getTabLevel() != 0) // maintain form on header when zooming to a detail tab
tabPanel.switchRowPresentation();
if (wasForm) {
// maintain form on header when zooming to a detail tab
if (tabPanel.getTabLevel() == 0 && headerTab.getTabLevel() != 0) {
tabPanel.switchRowPresentation();
} else {
Component parent = tabPanel.getParent();
while (parent != null) {
if (parent instanceof DetailPane.Tabpanel) {
DetailPane.Tabpanel dtp = (Tabpanel) parent;
if (dtp.isToggleToFormView()) {
tabPanel.switchRowPresentation();
dtp.afterToggle();
}
break;
}
parent = parent.getParent();
}
}
}
}
private void invalidateTabPanel(IADTabpanel tabPanel) {

View File

@ -1,12 +1,34 @@
/**
*
*/
/***********************************************************************
* This file is part of iDempiere ERP Open Source *
* http://www.idempiere.org *
* *
* Copyright (C) Contributors *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
* MA 02110-1301, USA. *
* *
* Contributors: *
* - hengsin *
**********************************************************************/
package org.adempiere.webui.adwindow;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.adempiere.base.IServiceHolder;
import org.adempiere.webui.ClientInfo;
@ -18,7 +40,6 @@ import org.adempiere.webui.component.Label;
import org.adempiere.webui.component.Panel;
import org.adempiere.webui.component.Tab;
import org.adempiere.webui.component.Tabbox;
import org.adempiere.webui.component.Tabpanel;
import org.adempiere.webui.component.ToolBar;
import org.adempiere.webui.component.ToolBarButton;
import org.adempiere.webui.component.Window;
@ -26,6 +47,9 @@ import org.adempiere.webui.session.SessionManager;
import org.adempiere.webui.theme.ThemeManager;
import org.adempiere.webui.util.ZKUpdateUtil;
import org.adempiere.webui.window.CustomizeGridViewDialog;
import org.adempiere.webui.window.WRecordInfo;
import org.compiere.model.DataStatusEvent;
import org.compiere.model.GridTab;
import org.compiere.model.MToolBarButton;
import org.compiere.util.Env;
import org.compiere.util.Msg;
@ -36,6 +60,7 @@ import org.zkoss.zk.au.out.AuScript;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Execution;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.HtmlBasedComponent;
import org.zkoss.zk.ui.IdSpace;
import org.zkoss.zk.ui.Page;
import org.zkoss.zk.ui.event.Event;
@ -44,8 +69,11 @@ import org.zkoss.zk.ui.event.Events;
import org.zkoss.zk.ui.event.KeyEvent;
import org.zkoss.zk.ui.sys.ExecutionCtrl;
import org.zkoss.zk.ui.util.Clients;
import org.zkoss.zul.A;
import org.zkoss.zul.Div;
import org.zkoss.zul.Hbox;
import org.zkoss.zul.Hlayout;
import org.zkoss.zul.Popup;
import org.zkoss.zul.Separator;
import org.zkoss.zul.Space;
import org.zkoss.zul.Tabpanels;
@ -57,10 +85,11 @@ import org.zkoss.zul.Toolbar;
*
*/
public class DetailPane extends Panel implements EventListener<Event>, IdSpace {
/**
*
* generated serial id
*/
private static final long serialVersionUID = 8807016961597158305L;
private static final long serialVersionUID = -6994505162094868814L;
private static final String BTN_PROCESS_ID = "BtnProcess";
@ -76,9 +105,11 @@ public class DetailPane extends Panel implements EventListener<Event>, IdSpace {
private static final String BTN_CUSTOMIZE_ID = "BtnCustomize";
private static final String BTN_TOGGLE_ID = "BtnToggle";
private static final String TABBOX_ONSELECT_ATTRIBUTE = "detailpane.tabbox.onselect";
public static final String ON_POST_SELECT_TAB_EVENT = "onPostSelectTab";
private static final String ON_POST_SELECT_TAB_EVENT = "onPostSelectTab";
private static final String STATUS_TEXT_ATTRIBUTE = "status.text";
@ -91,9 +122,9 @@ public class DetailPane extends Panel implements EventListener<Event>, IdSpace {
private static final String PROCESS_IMAGE = "images/Process16.png";
private static final String SAVE_IMAGE = "images/Save16.png";
private static final String QUICK_FORM_IMAGE = "images/QuickForm16.png";
private static final String TOGGLE_IMAGE = "images/Multi16.png";
private ToolBarButton btnNew;
private long prevKeyEventTime = 0;
private KeyEvent prevKeyEvent;
@ -121,9 +152,11 @@ public class DetailPane extends Panel implements EventListener<Event>, IdSpace {
public static final String ON_QUICK_FORM_EVENT = "onQuickForm";
private HashMap<String, ToolBarButton> buttons = new HashMap<String, ToolBarButton>();
private List<ToolbarCustomButton> toolbarCustomButtons = new ArrayList<ToolbarCustomButton>();
public static final String ON_RECORD_NAVIGATE_EVENT = "onRecordNavigate";
/**
* default constructor
*/
public DetailPane() {
tabbox = new Tabbox();
tabbox.setParent(this);
@ -280,25 +313,24 @@ public class DetailPane extends Panel implements EventListener<Event>, IdSpace {
}
Tabpanel tp = new Tabpanel();
tabpanels.appendChild(tp);
tp.setSclass("adwindow-detailpane-tabpanel");
ToolBar toolbar = new ToolBar();
tp.appendChild(toolbar);
btnNew = new ToolBarButton();
ToolBar toolbar = tp.getToolbar();
HashMap<String, ToolBarButton> buttons = new HashMap<String, ToolBarButton>();
ToolBarButton button = new ToolBarButton();
if (ThemeManager.isUseFontIconForImage())
btnNew.setIconSclass("z-icon-New");
button.setIconSclass("z-icon-New");
else
btnNew.setImage(ThemeManager.getThemeResource(NEW_IMAGE));
btnNew.setId(BTN_NEW_ID);
btnNew.addEventListener(Events.ON_CLICK, new EventListener<Event>() {
button.setImage(ThemeManager.getThemeResource(NEW_IMAGE));
button.setId(BTN_NEW_ID);
button.addEventListener(Events.ON_CLICK, new EventListener<Event>() {
@Override
public void onEvent(Event event) throws Exception {
onNew();
if (event.getTarget().isVisible())
onNew();
}
});
btnNew.setTooltiptext(Util.cleanAmp(Msg.getMsg(Env.getCtx(), "New")) + " Shift+Alt+N");
buttons.put(BTN_NEW_ID.substring(3, BTN_NEW_ID.length()), btnNew);
ToolBarButton button = new ToolBarButton();
button.setTooltiptext(Util.cleanAmp(Msg.getMsg(Env.getCtx(), "New")) + " Shift+Alt+N");
buttons.put(BTN_NEW_ID.substring(3, BTN_NEW_ID.length()), button);
button = new ToolBarButton();
if (ThemeManager.isUseFontIconForImage())
@ -309,10 +341,11 @@ public class DetailPane extends Panel implements EventListener<Event>, IdSpace {
button.addEventListener(Events.ON_CLICK, new EventListener<Event>() {
@Override
public void onEvent(Event event) throws Exception {
onEdit(true);
if (event.getTarget().isVisible())
onEdit(true);
}
});
button.setTooltiptext(Util.cleanAmp(Msg.getMsg(Env.getCtx(), "EditRecord")));
button.setTooltiptext(Util.cleanAmp(Msg.getMsg(Env.getCtx(), "EditRecord")) + " Shift+Alt+E");
buttons.put(BTN_EDIT_ID.substring(3, BTN_EDIT_ID.length()), button);
button = new ToolBarButton();
@ -324,11 +357,13 @@ public class DetailPane extends Panel implements EventListener<Event>, IdSpace {
button.addEventListener(Events.ON_CLICK, new EventListener<Event>() {
@Override
public void onEvent(Event event) throws Exception {
Event openEvent = new Event(ON_DELETE_EVENT, DetailPane.this);
eventListener.onEvent(openEvent);
if (event.getTarget().isVisible()) {
Event openEvent = new Event(ON_DELETE_EVENT, DetailPane.this);
eventListener.onEvent(openEvent);
}
}
});
button.setTooltiptext(Util.cleanAmp(Msg.getMsg(Env.getCtx(), "Delete")));
button.setTooltiptext(Util.cleanAmp(Msg.getMsg(Env.getCtx(), "Delete")) + " Shift+Alt+D");
buttons.put(BTN_DELETE_ID.substring(3, BTN_DELETE_ID.length()), button);
button = new ToolBarButton();
@ -340,13 +375,14 @@ public class DetailPane extends Panel implements EventListener<Event>, IdSpace {
button.addEventListener(Events.ON_CLICK, new EventListener<Event>() {
@Override
public void onEvent(Event event) throws Exception {
Event openEvent = new Event(ON_SAVE_EVENT, DetailPane.this);
eventListener.onEvent(openEvent);
if (event.getTarget().isVisible()) {
Event openEvent = new Event(ON_SAVE_EVENT, DetailPane.this);
eventListener.onEvent(openEvent);
}
}
});
button.setTooltiptext(Util.cleanAmp(Msg.getMsg(Env.getCtx(), "Save")));
button.setTooltiptext(Util.cleanAmp(Msg.getMsg(Env.getCtx(), "Save")) + " Shift+Alt+S");
buttons.put(BTN_SAVE_ID.substring(3, BTN_SAVE_ID.length()), button);
if (!tabPanel.getGridTab().isSortTab()) {
button = new ToolBarButton();
@ -358,10 +394,11 @@ public class DetailPane extends Panel implements EventListener<Event>, IdSpace {
button.addEventListener(Events.ON_CLICK, new EventListener<Event>() {
@Override
public void onEvent(Event event) throws Exception {
onProcess(event.getTarget());
if (event.getTarget().isVisible())
onProcess(event.getTarget());
}
});
button.setTooltiptext(Util.cleanAmp(Msg.getMsg(Env.getCtx(), "Process")));
button.setTooltiptext(Util.cleanAmp(Msg.getMsg(Env.getCtx(), "Process")) + " Shift+Alt+O");
buttons.put(BTN_PROCESS_ID.substring(3, BTN_PROCESS_ID.length()), button);
}
@ -376,8 +413,10 @@ public class DetailPane extends Panel implements EventListener<Event>, IdSpace {
@Override
public void onEvent(Event event) throws Exception
{
Event openEvent = new Event(ON_QUICK_FORM_EVENT, DetailPane.this);
eventListener.onEvent(openEvent);
if (event.getTarget().isVisible()) {
Event openEvent = new Event(ON_QUICK_FORM_EVENT, DetailPane.this);
eventListener.onEvent(openEvent);
}
}
});
button.setTooltiptext(Util.cleanAmp(Msg.getMsg(Env.getCtx(), "QuickForm")));
@ -390,9 +429,20 @@ public class DetailPane extends Panel implements EventListener<Event>, IdSpace {
else
button.setImage(ThemeManager.getThemeResource(CUSTOMIZE_IMAGE));
button.setId(BTN_CUSTOMIZE_ID);
button.addEventListener(Events.ON_CLICK, e -> onCustomize(e));
button.addEventListener(Events.ON_CLICK, e -> { if(e.getTarget().isVisible()) onCustomize(e); });
button.setTooltiptext(Util.cleanAmp(Msg.getMsg(Env.getCtx(), "Customize")));
buttons.put(BTN_CUSTOMIZE_ID.substring(3, BTN_CUSTOMIZE_ID.length()), button);
// ADD toggle grid button
button = new ToolBarButton();
if (ThemeManager.isUseFontIconForImage())
button.setIconSclass("z-icon-Multi");
else
button.setImage(ThemeManager.getThemeResource(TOGGLE_IMAGE));
button.setId(BTN_TOGGLE_ID);
button.addEventListener(Events.ON_CLICK, e -> { if(e.getTarget().isVisible()) onToggle(e); });
button.setTooltiptext(Util.cleanAmp(Msg.getMsg(Env.getCtx(), "Toggle")) + " Shift+Alt+T");
buttons.put(BTN_TOGGLE_ID.substring(3, BTN_TOGGLE_ID.length()), button);
MToolBarButton[] officialButtons = MToolBarButton.getToolbarButtons("D", null);
for (MToolBarButton toolbarButton : officialButtons) {
@ -428,7 +478,7 @@ public class DetailPane extends Panel implements EventListener<Event>, IdSpace {
}
ToolbarCustomButton toolbarCustomBtn = new ToolbarCustomButton(toolbarButton, btn, actionId, tabPanel.getGridTab().getWindowNo());
toolbarCustomButtons.add(toolbarCustomBtn);
tp.toolbarCustomButtons.add(toolbarCustomBtn);
toolbar.appendChild(btn);
}
@ -456,7 +506,15 @@ public class DetailPane extends Panel implements EventListener<Event>, IdSpace {
messageContainers.put(tabLabel.AD_Tab_ID, messageContainer);
tabPanel.setAttribute("AD_Tab_ID", tabLabel.AD_Tab_ID);
tp.appendChild(tabPanel);
if (ClientInfo.isMobile() && ClientInfo.maxWidth(ClientInfo.SMALL_WIDTH)) {
tp.createOverflowButton();
}
RecordToolbar recordToolbar = new RecordToolbar(tabPanel.getGridTab());
recordToolbar.addEventListener(ON_RECORD_NAVIGATE_EVENT, eventListener);
tp.setRecordToolbar(recordToolbar);
tp.setADTabpanel(tabPanel);
if (tabPanel.getGridView() != null) {
tabPanel.addEventListener(ADTabpanel.ON_DYNAMIC_DISPLAY_EVENT, this);
tabPanel.getGridView().addEventListener(ON_EDIT_EVENT, new EventListener<Event>() {
@ -470,6 +528,30 @@ public class DetailPane extends Panel implements EventListener<Event>, IdSpace {
}
}
/**
* toggle between grid and form view
* @param e
*/
protected void onToggle(Event e) {
var adTabPanel = getSelectedADTabpanel();
if(!(adTabPanel instanceof ADSortTab)) {
adTabPanel.switchRowPresentation();
getSelectedPanel().getToolbarButton(BTN_CUSTOMIZE_ID).setDisabled(!adTabPanel.isGridView());
Tabpanel tabPanel = (Tabpanel) tabbox.getSelectedTabpanel();
tabPanel.setToggleToFormView(!adTabPanel.isGridView());
tabPanel.afterToggle();
if (adTabPanel != null && adTabPanel instanceof HtmlBasedComponent) {
((HtmlBasedComponent)adTabPanel).focus();
}
}
}
/**
* open customize grid dialog
* @param e
*/
protected void onCustomize(Event e) {
if (getSelectedADTabpanel() instanceof ADTabpanel) {
ADTabpanel tabPanel = (ADTabpanel) getSelectedADTabpanel();
@ -477,6 +559,10 @@ public class DetailPane extends Panel implements EventListener<Event>, IdSpace {
}
}
/**
* open process dropdown
* @param button
*/
protected void onProcess(Component button) {
ProcessButtonPopup popup = new ProcessButtonPopup();
ADTabpanel adtab = (ADTabpanel) getSelectedADTabpanel();
@ -539,6 +625,14 @@ public class DetailPane extends Panel implements EventListener<Event>, IdSpace {
return null;
}
/**
*
* @return {@link Tabpanel}
*/
public Tabpanel getSelectedPanel() {
return (Tabpanel) tabbox.getSelectedPanel();
}
/**
*
* @param status
@ -589,6 +683,13 @@ public class DetailPane extends Panel implements EventListener<Event>, IdSpace {
}
messageContainer.appendChild(new Space());
if (!tabPanel.isGridView()) {
Tabpanel tp = (Tabpanel) tabbox.getSelectedTabpanel();
if (tp.getRecordToolbar() != null) {
tp.getRecordToolbar().dynamicDisplay();
}
}
}
private String buildLabelText(String statusText) {
@ -721,8 +822,8 @@ public class DetailPane extends Panel implements EventListener<Event>, IdSpace {
int index = getSelectedIndex();
if (index < 0 || index >= getTabcount()) return;
Tabpanel tabpanel = tabbox.getTabpanel(index);
Toolbar toolbar = (Toolbar) tabpanel.getFirstChild();
Tabpanel tabpanel = (Tabpanel) tabbox.getTabpanel(index);
Toolbar toolbar = tabpanel.getToolbar();
IADTabpanel adtab = getADTabpanel(index);
if (adtab == null)
@ -743,7 +844,7 @@ public class DetailPane extends Panel implements EventListener<Event>, IdSpace {
deleteRecord = adtab.getGridTab().isDeleteRecord();
}
boolean enableDelete = !changed && deleteRecord && !adtab.getGridTab().isSortTab();
boolean enableCustomize = !adtab.getGridTab().isSortTab();
boolean enableCustomize = !adtab.getGridTab().isSortTab() && adtab.isGridView();
ADWindow adwindow = ADWindow.findADWindow(this);
if (adwindow == null)
@ -764,9 +865,10 @@ public class DetailPane extends Panel implements EventListener<Event>, IdSpace {
btn.setDisabled(!adtab.needSave(true, false));
} else if (BTN_CUSTOMIZE_ID.equals(btn.getId())) {
btn.setDisabled(!enableCustomize);
}
else if (BTN_QUICK_FORM_ID.equals(btn.getId())) {
} else if (BTN_QUICK_FORM_ID.equals(btn.getId())) {
btn.setDisabled(!(adtab.isEnableQuickFormButton() && !adtab.getGridTab().isReadOnly()));
} else if (BTN_TOGGLE_ID.equals(btn.getId())) {
btn.setDisabled(adtab.getGridTab().isSortTab());
}
if (windowRestrictList.contains(btn.getId())) {
btn.setVisible(false);
@ -783,8 +885,8 @@ public class DetailPane extends Panel implements EventListener<Event>, IdSpace {
int index = getSelectedIndex();
if (index < 0 || index >= getTabcount()) return;
Tabpanel tabpanel = tabbox.getTabpanel(index);
Toolbar toolbar = (Toolbar) tabpanel.getFirstChild();
Tabpanel tabpanel = (Tabpanel) tabbox.getTabpanel(index);
Toolbar toolbar = tabpanel.getToolbar();
IADTabpanel adtab = getADTabpanel(index);
if (adtab == null) return;
@ -886,8 +988,8 @@ public class DetailPane extends Panel implements EventListener<Event>, IdSpace {
int index = getSelectedIndex();
if (index < 0 || index >= getTabcount()) return;
Tabpanel tabpanel = tabbox.getTabpanel(index);
Toolbar toolbar = (Toolbar) tabpanel.getFirstChild();
Tabpanel tabpanel = (Tabpanel) tabbox.getTabpanel(index);
Toolbar toolbar = tabpanel.getToolbar();
for(Component c : toolbar.getChildren()) {
if (c instanceof ToolBarButton) {
ToolBarButton btn = (ToolBarButton) c;
@ -907,19 +1009,48 @@ public class DetailPane extends Panel implements EventListener<Event>, IdSpace {
return null;
}
/**
* add new record
* @throws Exception
*/
public void onNew() throws Exception {
Event openEvent = new Event(ON_NEW_EVENT, DetailPane.this);
eventListener.onEvent(openEvent);
}
public static final int VK_N = 0x4E;
private static final int VK_N = 0x4E;
private static final int VK_T = 0x54;
private static final int VK_E = 0x45;
private static final int VK_S = 0x53;
private static final int VK_D = 0x44;
private static final int VK_O = 0x4F;
private void onCtrlKeyEvent(KeyEvent keyEvent) {
ToolBarButton btn = null;
if (keyEvent.isAltKey() && !keyEvent.isCtrlKey() && keyEvent.isShiftKey()) { // Shift+Alt key
if (keyEvent.getKeyCode() == VK_N) { // Shift+Alt+N
btn = btnNew;
btn = getSelectedPanel().getToolbarButton(BTN_NEW_ID);
} else if (keyEvent.getKeyCode() == VK_T) {
btn = getSelectedPanel().getToolbarButton(BTN_TOGGLE_ID);
} else if (keyEvent.getKeyCode() == KeyEvent.HOME) {
btn = getSelectedPanel().getRecordToolbar().btnFirst;
} else if (keyEvent.getKeyCode() == KeyEvent.END) {
btn = getSelectedPanel().getRecordToolbar().btnLast;
} else if (keyEvent.getKeyCode() == KeyEvent.LEFT) {
btn = getSelectedPanel().getRecordToolbar().btnPrevious;
} else if (keyEvent.getKeyCode() == KeyEvent.RIGHT) {
btn = getSelectedPanel().getRecordToolbar().btnNext;
} else if (keyEvent.getKeyCode() == KeyEvent.HOME) {
btn = getSelectedPanel().getRecordToolbar().btnFirst;
} else if (keyEvent.getKeyCode() == VK_E) {
btn = getSelectedPanel().getToolbarButton(BTN_EDIT_ID);
} else if (keyEvent.getKeyCode() == VK_S) {
btn = getSelectedPanel().getToolbarButton(BTN_SAVE_ID);
} else if (keyEvent.getKeyCode() == VK_D) {
btn = getSelectedPanel().getToolbarButton(BTN_DELETE_ID);
} else if (keyEvent.getKeyCode() == VK_O) {
btn = getSelectedPanel().getToolbarButton(BTN_PROCESS_ID);
}
}
}
if (btn != null) {
prevKeyEventTime = System.currentTimeMillis();
prevKeyEvent = keyEvent;
@ -934,4 +1065,278 @@ public class DetailPane extends Panel implements EventListener<Event>, IdSpace {
}
}
/**
* tabpanel for adtabpanel
* @author hengsin
*
*/
public static class Tabpanel extends org.adempiere.webui.component.Tabpanel {
/**
*
*/
private static final long serialVersionUID = 8248794614430375822L;
private ToolBar toolbar;
private RecordToolbar recordToolBar;
private Div pagingControl;
private boolean toggleToFormView = false;
private IADTabpanel adTabPanel;
private List<ToolbarCustomButton> toolbarCustomButtons = new ArrayList<ToolbarCustomButton>();
private A overflowButton;
private Popup overflowPopup;
public Tabpanel() {
setSclass("adwindow-detailpane-tabpanel");
toolbar = new ToolBar();
appendChild(toolbar);
}
/**
* update toolbar state after toggle between grid and form view
*/
public void afterToggle() {
if (getPagingControl() != null)
getPagingControl().setVisible(!toggleToFormView);
if (getRecordToolbar() != null) {
getRecordToolbar().setVisible(toggleToFormView);
if (getRecordToolbar().isVisible())
getRecordToolbar().dynamicDisplay();
}
boolean enableCustomize = !adTabPanel.getGridTab().isSortTab() && adTabPanel.isGridView();
List<ToolBarButton> btns = getToolbar().getChildren();
Optional<ToolBarButton> optional = btns.stream().filter(e -> BTN_CUSTOMIZE_ID.equals(e.getId())).findFirst();
if (optional.isPresent())
optional.get().setDisabled(!enableCustomize);
}
/**
* set form view state
* @param b
*/
public void setToggleToFormView(boolean b) {
toggleToFormView = b;
}
/**
*
* @return true if tab have been toggle to form view
*/
public boolean isToggleToFormView() {
return toggleToFormView;
}
/**
*
* @param tabPanel
*/
public void setADTabpanel(IADTabpanel tabPanel) {
appendChild(tabPanel);
this.adTabPanel = tabPanel;
if (tabPanel instanceof ADTabpanel) {
tabPanel.addEventListener(ADTabpanel.ON_SWITCH_VIEW_EVENT, e -> {
if (recordToolBar != null && tabPanel.isGridView()) {
recordToolBar.setVisible(false);
}
});
}
}
/**
* Get toolbar of the tabpanel
* @return {@link ToolBar}
*/
public ToolBar getToolbar() {
return toolbar;
}
/**
* set record navigation toolbar
* @param rtb
*/
public void setRecordToolbar(RecordToolbar rtb) {
recordToolBar = rtb;
Component parent = overflowPopup != null ? overflowPopup : toolbar;
parent.appendChild(rtb);
rtb.setVisible(false);
if (overflowPopup == null)
rtb.setSclass("adwindow-detailpane-adtab-grid-south");
}
/**
*
* @return {@link RecordToolbar}
*/
public RecordToolbar getRecordToolbar() {
return recordToolBar;
}
/**
* set paging control container
* @param pagingControl
*/
public void setPagingControl(Div pagingControl) {
Component parent = overflowPopup != null ? overflowPopup : toolbar;
if ( pagingControl.getParent() != parent) {
parent.appendChild(pagingControl);
ZKUpdateUtil.setHflex(pagingControl, "0");
if (overflowPopup == null)
pagingControl.setSclass("adwindow-detailpane-adtab-grid-south");
}
this.pagingControl = pagingControl;
}
/**
*
* @return paging control container
*/
public Div getPagingControl() {
return pagingControl;
}
/**
* Get toolbar button by id
* @param id
* @return {@link ToolBarButton}
*/
public ToolBarButton getToolbarButton(String id) {
List<ToolBarButton> list = toolbar.getChildren();
Optional<ToolBarButton> optional = list.stream().filter(e -> e.getId().equals(id)).findFirst();
return optional.isPresent() ? optional.get() : null;
}
private void createOverflowButton() {
overflowButton = new A();
overflowButton.setTooltiptext(Msg.getMsg(Env.getCtx(), "ShowMore"));
overflowButton.setIconSclass("z-icon-ShowMore");
overflowButton.setSclass("font-icon-toolbar-button toolbar-button mobile-overflow-link");
toolbar.appendChild(overflowButton);
newOverflowPopup();
toolbar.appendChild(overflowPopup);
overflowButton.addEventListener(Events.ON_CLICK, e -> {
Long ts = (Long) overflowPopup.removeAttribute("popup.close");
if (ts != null) {
if (System.currentTimeMillis() - ts.longValue() < 500) {
return;
}
}
overflowPopup.open(overflowButton, "after_end");
});
}
private void newOverflowPopup() {
overflowPopup = new Popup();
overflowPopup.setHflex("min");
overflowPopup.setVflex("min");
}
}
/**
* record navigation toolbar
* @author hengsin
*
*/
private static class RecordToolbar extends Hlayout {
/**
*
*/
private static final long serialVersionUID = 5024630043211194429L;
private ToolBarButton btnFirst;
private ToolBarButton btnPrevious;
private ToolBarButton btnRecordInfo;
private ToolBarButton btnNext;
private ToolBarButton btnLast;
private GridTab gridTab;
private RecordToolbar(GridTab gridTab) {
this.gridTab = gridTab;
btnFirst = createButton("First", "First", "First");
btnFirst.setTooltiptext(btnFirst.getTooltiptext()+" Shift+Alt+Home");
appendChild(btnFirst);
btnFirst.addEventListener(Events.ON_CLICK, e -> {
Event ne = new Event(DetailPane.ON_RECORD_NAVIGATE_EVENT, this, "first");
Events.sendEvent(this, ne);
});
btnPrevious = createButton("Previous", "Previous", "Previous");
btnPrevious.setTooltiptext(btnPrevious.getTooltiptext()+" Shift+Alt+Left");
appendChild(btnPrevious);
btnPrevious.addEventListener(Events.ON_CLICK, e -> {
Event ne = new Event(DetailPane.ON_RECORD_NAVIGATE_EVENT, this, "previous");
Events.sendEvent(this, ne);
});
btnRecordInfo = new ToolBarButton();
btnRecordInfo.setLabel("");
btnRecordInfo.setTooltiptext(Util.cleanAmp(Msg.getMsg(Env.getCtx(), "Who")));
btnRecordInfo.addEventListener(Events.ON_CLICK, e -> {
if (gridTab.isNew() || gridTab.getRowCount() == 0)
return;
DataStatusEvent dse = new DataStatusEvent(gridTab, gridTab.getRowCount(), gridTab.needSave(true, true), true, false);
gridTab.updateDataStatusEventProperties(dse);
dse.setCurrentRow(gridTab.getCurrentRow());
String title = Msg.getMsg(Env.getCtx(), "Who") + btnRecordInfo.getLabel();
new WRecordInfo(title, dse, gridTab);
});
btnRecordInfo.setSclass("breadcrumb-record-info link");
btnRecordInfo.setId("recordInfo");
btnRecordInfo.setStyle("float: none; display: inline-flex; width: auto;");
appendChild(btnRecordInfo);
btnNext = createButton("Next", "Next", "Next");
btnNext.setTooltiptext(btnNext.getTooltiptext()+" Shift+Alt+Right");
btnNext.addEventListener(Events.ON_CLICK, e -> {
Event ne = new Event(DetailPane.ON_RECORD_NAVIGATE_EVENT, this, "next");
Events.sendEvent(this, ne);
});
appendChild(btnNext);
btnLast = createButton("Last", "Last", "Last");
btnLast.setTooltiptext(btnLast.getTooltiptext()+" Shift+Alt+End");
btnLast.addEventListener(Events.ON_CLICK, e -> {
Event ne = new Event(DetailPane.ON_RECORD_NAVIGATE_EVENT, this, "last");
Events.sendEvent(this, ne);
});
appendChild(btnLast);
this.setValign("middle");
}
private ToolBarButton createButton(String name, String image, String tooltip)
{
ToolBarButton btn = new ToolBarButton("");
btn.setName("Btn"+name);
btn.setId(name);
String suffix = "16.png";
if (ThemeManager.isUseFontIconForImage())
btn.setIconSclass("z-icon-"+image+"Record");
else
btn.setImage(ThemeManager.getThemeResource("images/"+image + suffix));
btn.setTooltiptext(Msg.getMsg(Env.getCtx(),tooltip));
btn.setSclass("breadcrumb-toolbar-button");
this.appendChild(btn);
//make toolbar button last to receive focus
btn.setTabindex(0);
btn.setDisabled(true);
btn.setStyle("float: none");
return btn;
}
private void dynamicDisplay() {
int rowCount = gridTab.getRowCount();
int currentRow = gridTab.getCurrentRow()+1;
btnRecordInfo.setLabel(currentRow+"/"+rowCount);
btnFirst.setDisabled(currentRow<=1);
btnPrevious.setDisabled(currentRow<=1);
btnNext.setDisabled(currentRow==rowCount);
btnLast.setDisabled(currentRow==rowCount);
this.invalidate();
}
}
}

View File

@ -63,7 +63,6 @@ import org.zkoss.zul.Column;
import org.zkoss.zul.Div;
import org.zkoss.zul.Paging;
import org.zkoss.zul.Row;
import org.zkoss.zul.Tabpanel;
import org.zkoss.zul.Vlayout;
import org.zkoss.zul.event.ZulEvents;
import org.zkoss.zul.impl.CustomGridDataLoader;
@ -1295,13 +1294,8 @@ public class GridView extends Vlayout implements EventListener<Event>, IdSpace,
if (isDetailPane()) {
Component parent = this.getParent();
while (parent != null) {
if (parent instanceof Tabpanel) {
Component firstChild = parent.getFirstChild();
if ( gridFooter.getParent() != firstChild ) {
firstChild.appendChild(gridFooter);
ZKUpdateUtil.setHflex(gridFooter, "0");
gridFooter.setSclass("adwindow-detailpane-adtab-grid-south");
}
if (parent instanceof DetailPane.Tabpanel) {
((DetailPane.Tabpanel) parent).setPagingControl(gridFooter);
break;
}
parent = parent.getParent();

View File

@ -195,4 +195,12 @@ public interface IADTabpanel extends Component, Evaluatee {
* @return Quick Form Button Enabled/Disabled
*/
public abstract boolean isEnableQuickFormButton();
/**
* Get is detail pane visible
* @return boolean
*/
public default boolean isDetailVisible() {
return false;
}
}