IDEMPIERE-369 Master Detail layout improvements. 1) Make the opening of window and switching between header and detail tab faster. 2) Implemented lazy loading for collapsed detail tabs. 3) Remember the collapsed/open state of detail tabs. 4) Improvement to the breadcrumbe popup menu.

This commit is contained in:
Heng Sin Low 2013-01-29 00:19:49 +08:00
parent 70c91a34c9
commit 9e7ea1ba96
13 changed files with 798 additions and 200 deletions

View File

@ -74,6 +74,11 @@ public final class LayoutUtils {
|| ((" " + sclass + " ").indexOf(" " + cls + " ") > -1);
}
/**
*
* @param label
* @return wrapped label
*/
public static Component makeRightAlign(Label label) {
Div div = new Div();
div.setStyle("text-align: right");
@ -154,6 +159,10 @@ public final class LayoutUtils {
Clients.response("_openPopupWindow_", new AuScript(window, script.toString()));
}
/**
*
* @param component
*/
public static void redraw(AbstractComponent component) {
StringWriter writer = new StringWriter(1024);
try {
@ -163,4 +172,20 @@ public final class LayoutUtils {
e.printStackTrace();
}
}
/**
* @param component
* @return true if the component and all its parent are visible
*/
public static boolean isReallyVisible(Component component) {
if (!component.isVisible()) return false;
Component parent = component.getParent();
while (parent != null) {
if (!parent.isVisible())
return false;
parent = parent.getParent();
}
return true;
}
}

View File

@ -229,16 +229,9 @@ public class ValuePreference extends Window implements EventListener<Event>
}
} // ValuePreference
private AbstractADWindowContent findADWindowContent(Component ref) {
Component parent = ref.getParent();
while(parent != null) {
if (parent.getAttribute(ADWindow.AD_WINDOW_ATTRIBUTE_KEY) != null) {
ADWindow adwindow = (ADWindow) parent.getAttribute(ADWindow.AD_WINDOW_ATTRIBUTE_KEY);
return adwindow.getADWindowContent();
}
parent = parent.getParent();
}
return null;
private AbstractADWindowContent findADWindowContent(Component comp) {
ADWindow adwindow = ADWindow.findADWindow(comp);
return adwindow != null ? adwindow.getADWindowContent() : null;
}
private Properties m_ctx;

View File

@ -936,7 +936,7 @@ public class ADSortTab extends Panel implements IADTabpanel
}
@Override
public boolean isActive() {
public boolean isActivated() {
return active;
}
@ -979,5 +979,14 @@ public class ADSortTab extends Panel implements IADTabpanel
public int getTabNo() {
return tabNo;
}
@Override
public void setDetailPane(DetailPane detailPane) {
}
@Override
public DetailPane getDetailPane() {
return null;
}
} //ADSortTab

View File

@ -55,11 +55,15 @@ import org.compiere.model.DataStatusListener;
import org.compiere.model.GridField;
import org.compiere.model.GridTab;
import org.compiere.model.GridWindow;
import org.compiere.model.I_AD_Preference;
import org.compiere.model.MLookup;
import org.compiere.model.MPreference;
import org.compiere.model.MTable;
import org.compiere.model.MToolBarButton;
import org.compiere.model.MToolBarButtonRestrict;
import org.compiere.model.MTree;
import org.compiere.model.MTreeNode;
import org.compiere.model.Query;
import org.compiere.model.X_AD_FieldGroup;
import org.compiere.model.X_AD_ToolBarButton;
import org.compiere.util.CLogger;
@ -70,13 +74,13 @@ import org.compiere.util.Msg;
import org.compiere.util.Util;
import org.zkoss.zk.au.out.AuFocus;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Desktop;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.HtmlBasedComponent;
import org.zkoss.zk.ui.IdSpace;
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.OpenEvent;
import org.zkoss.zk.ui.util.Clients;
import org.zkoss.zul.Button;
import org.zkoss.zul.Cell;
@ -84,6 +88,7 @@ import org.zkoss.zul.Center;
import org.zkoss.zul.DefaultTreeNode;
import org.zkoss.zul.Div;
import org.zkoss.zul.Separator;
import org.zkoss.zul.South;
import org.zkoss.zul.Space;
import org.zkoss.zul.Style;
import org.zkoss.zul.TreeModel;
@ -108,6 +113,8 @@ import org.zkoss.zul.impl.XulElement;
public class ADTabpanel extends Div implements Evaluatee, EventListener<Event>,
DataStatusListener, IADTabpanel, IdSpace
{
private static final String ON_SAVE_OPEN_PREFERENCE_EVENT = "onSaveOpenPreference";
public static final String ON_POST_INIT_EVENT = "onPostInit";
public static final String ON_SWITCH_VIEW_EVENT = "onSwitchView";
@ -159,17 +166,17 @@ DataStatusListener, IADTabpanel, IdSpace
List<Group> allCollapsibleGroups = new ArrayList<Group>();
private Component formContainer = null;
private Borderlayout formContainer = null;
private ADTreePanel treePanel = null;
private GridTabDataBinder dataBinder;
private boolean active = false;
private boolean activated = false;
private Group currentGroup;
private Component detailPane;
private DetailPane detailPane;
private boolean detailPaneMode;
@ -195,6 +202,7 @@ DataStatusListener, IADTabpanel, IdSpace
}
});
addEventListener(ON_POST_INIT_EVENT, this);
addEventListener(ON_SAVE_OPEN_PREFERENCE_EVENT, this);
}
private void initComponents()
@ -214,19 +222,32 @@ DataStatusListener, IADTabpanel, IdSpace
listPanel.getListbox().addEventListener(Events.ON_DOUBLE_CLICK, this);
}
public void addDetails(Component component) {
public void setDetailPane(DetailPane component) {
detailPane = component;
if (formContainer instanceof Borderlayout) {
Borderlayout borderLayout = (Borderlayout) formContainer;
borderLayout.appendSouth(detailPane);
borderLayout.getSouth().setCollapsible(true);
borderLayout.getSouth().setSplittable(true);
borderLayout.getSouth().setOpen(true);
borderLayout.getSouth().setSclass("adwindow-gridview-detail");
} else {
formContainer.appendChild(component);
Borderlayout borderLayout = (Borderlayout) formContainer;
South south = borderLayout.getSouth();
if (south == null) {
south = new South();
borderLayout.appendChild(south);
south.setWidgetOverride("doClick_", "function (evt){this.$doClick_(evt);" +
"var target = evt.domTarget;if (!target.id) target = target.parentNode;" +
"if(this.$n('colled') == target) {" +
"var se = new zk.Event(this, 'onSlide', null, {toServer: true}); zAu.send(se); } }");
south.addEventListener(Events.ON_OPEN, this);
south.addEventListener("onSlide", this);
}
south.appendChild(component);
south.setVisible(true);
south.setCollapsible(true);
south.setSplittable(true);
south.setOpen(isOpenDetailPane());
south.setSclass("adwindow-gridview-detail");
}
public DetailPane getDetailPane() {
return detailPane;
}
/**
@ -291,6 +312,7 @@ DataStatusListener, IADTabpanel, IdSpace
div.setHflex("1");
div.setSclass("adtab-form");
div.setStyle("overflow-y: visible;");
div.setSpacing("0px");
layout.appendChild(center);
formContainer = layout;
@ -305,6 +327,7 @@ DataStatusListener, IADTabpanel, IdSpace
div.setStyle("overflow-y: visible;");
div.setVflex("1");
div.setWidth("100%");
div.setSpacing("0px");
StringBuilder cssContent = new StringBuilder();
cssContent.append(".adtab-form-borderlayout .z-south-colpsd:before { ");
@ -867,7 +890,7 @@ DataStatusListener, IADTabpanel, IdSpace
setAttribute(ATTR_ON_ACTIVATE_POSTED, Boolean.TRUE);
}
active = activate;
activated = activate;
if (listPanel.isVisible()) {
if (activate)
listPanel.activate(gridTab);
@ -941,15 +964,69 @@ DataStatusListener, IADTabpanel, IdSpace
windowPanel.onSavePayment();
}
else if (ON_POST_INIT_EVENT.equals(event.getName())) {
if (detailPane != null) {
Desktop desktop = Executions.getCurrent().getDesktop();
//for unknown reason, this is needed once per desktop to fixed the layout of the detailpane.
if (desktop.getAttribute("adtabpanel.detailpane.postinit.redraw") == null) {
desktop.setAttribute("adtabpanel.detailpane.postinit.redraw", Boolean.TRUE);
Events.postEvent(new Event(LayoutUtils.ON_REDRAW_EVENT, detailPane));
}
if (isDetailVisible() && detailPane.getSelectedADTabpanel() != null) {
detailPane.getSelectedADTabpanel().activate(true);
}
}
else if (event.getTarget() instanceof South) {
if (detailPane != null) {
boolean openEvent = event instanceof OpenEvent;
if (openEvent) {
Events.echoEvent(ON_SAVE_OPEN_PREFERENCE_EVENT, this, ((OpenEvent)event).isOpen());
if (!((OpenEvent)event).isOpen()) {
return;
}
}
if (detailPane.getParent() == null) {
formContainer.appendSouth(detailPane);
}
IADTabpanel tabPanel = detailPane.getSelectedADTabpanel();
if (tabPanel != null) {
if (!tabPanel.isActivated()) {
tabPanel.activate(true);
}
if (!tabPanel.isGridView()) {
tabPanel.switchRowPresentation();
}
}
}
}
else if (event.getName().equals(ON_SAVE_OPEN_PREFERENCE_EVENT)) {
Boolean value = (Boolean) event.getData();
int windowId = getGridTab().getAD_Window_ID();
int adTabId = getGridTab().getAD_Tab_ID();
if (windowId > 0 && adTabId > 0) {
Query query = new Query(Env.getCtx(), MTable.get(Env.getCtx(), I_AD_Preference.Table_ID), "AD_Window_ID=? AND Attribute=?", null);
MPreference preference = query.setOnlyActiveRecords(true)
.setApplyAccessFilter(true)
.setParameters(windowId, adTabId+"|DetailPane.IsOpen")
.first();
if (preference != null && preference.getAD_Preference_ID() > 0) {
preference.setValue(value ? "Y" : "N");
} else {
preference = new MPreference(Env.getCtx(), 0, null);
preference.setAD_Window_ID(windowId);
preference.setAttribute(adTabId+"|DetailPane.IsOpen");
preference.setValue(value ? "Y" : "N");
}
preference.save();
//update current context
Env.getCtx().setProperty("P"+windowId+"|"+adTabId+"|DetailPane.IsOpen", value ? "Y" : "N");
}
}
}
private boolean isOpenDetailPane() {
boolean open = true;
int windowId = getGridTab().getAD_Window_ID();
int adTabId = getGridTab().getAD_Tab_ID();
if (windowId > 0 && adTabId > 0) {
String preference = Env.getPreference(Env.getCtx(), windowId, adTabId+"|DetailPane.IsOpen", false);
if (preference != null && preference.trim().length() > 0) {
open = "Y".equals(preference);
}
}
return open;
}
private void navigateTo(DefaultTreeNode<MTreeNode> value) {
@ -1177,6 +1254,10 @@ DataStatusListener, IADTabpanel, IdSpace
listPanel.focus();
}
/**
*
* @param columnName
*/
public void setFocusToField(String columnName) {
if (formContainer.isVisible()) {
boolean found = false;
@ -1220,8 +1301,9 @@ DataStatusListener, IADTabpanel, IdSpace
return listPanel;
}
public boolean isActive() {
return active;
@Override
public boolean isActivated() {
return activated;
}
@Override
@ -1229,19 +1311,33 @@ DataStatusListener, IADTabpanel, IdSpace
if (this.detailPaneMode != detailPaneMode) {
this.detailPaneMode = detailPaneMode;
if (detailPaneMode) {
detailPane = null;
if (formContainer instanceof Borderlayout) {
Borderlayout borderLayout = (Borderlayout) formContainer;
if (borderLayout.getSouth() != null) {
borderLayout.getSouth().detach();
}
}
hideDetail();
} else {
showDetail();
}
this.setVflex("true");
listPanel.setDetailPaneMode(detailPaneMode);
}
}
private void showDetail() {
if (formContainer.getSouth() != null) {
formContainer.getSouth().setVisible(true);
if (formContainer.getSouth().isOpen() && detailPane != null && detailPane.getParent() == null) {
formContainer.appendSouth(detailPane);
}
}
}
private void hideDetail() {
if (formContainer.getSouth() != null) {
formContainer.getSouth().setVisible(false);
if (detailPane != null && detailPane.getParent() != null) {
detailPane.detach();
}
}
}
/**
* Get all visible button editors
* @return List<WButtonEditor>
@ -1287,5 +1383,46 @@ DataStatusListener, IADTabpanel, IdSpace
public int getTabNo() {
return tabNo;
}
/**
* activate current selected detail tab if it is visible
*/
public void activateDetailIfVisible() {
if (isDetailVisible()) {
IADTabpanel tabPanel = detailPane.getSelectedADTabpanel();
if (tabPanel != null && !tabPanel.isActivated()) {
tabPanel.activate(true);
if (!tabPanel.isGridView()) {
tabPanel.switchRowPresentation();
}
}
}
}
/**
*
* @return true if the detailpane is visible
*/
public boolean isDetailVisible() {
if (formContainer.getSouth() == null || !formContainer.getSouth().isVisible()
|| !formContainer.getSouth().isOpen()) {
return false;
}
return detailPane != null;
}
/**
*
* @return true if have one or more detail tabs
*/
public boolean hasDetailTabs() {
if (formContainer.getSouth() == null || !formContainer.getSouth().isVisible()) {
return false;
}
return detailPane != null && detailPane.getTabcount() > 0;
}
}

View File

@ -51,11 +51,22 @@ public class ADWindow extends AbstractUIPart
private static final CCache<Integer, AImage> imageCache = new CCache<Integer, AImage>(null, "WindowImageCache", 5, false);
/**
*
* @param ctx
* @param adWindowId
*/
public ADWindow(Properties ctx, int adWindowId)
{
this(ctx, adWindowId, null);
}
/**
*
* @param ctx
* @param adWindowId
* @param query
*/
public ADWindow(Properties ctx, int adWindowId, MQuery query)
{
if(adWindowId <= 0)
@ -75,11 +86,19 @@ public class ADWindow extends AbstractUIPart
image = windowContent.getImage();
}
/**
*
* @return title of window
*/
public String getTitle()
{
return _title;
}
/**
*
* @return image for the country
*/
public MImage getMImage()
{
return image;
@ -118,6 +137,7 @@ public class ADWindow extends AbstractUIPart
}
}
@Override
public Component getComponent() {
return windowPanelComponent;
}
@ -129,7 +149,28 @@ public class ADWindow extends AbstractUIPart
return windowContent;
}
/**
*
* @param windowNo
* @return adwindow instance for windowNo ( if any )
*/
public static ADWindow get(int windowNo) {
return (ADWindow) SessionManager.getAppDesktop().findWindow(windowNo);
}
/**
* @param comp
* @return adwindow instance if found, null otherwise
*/
public static ADWindow findADWindow(Component comp) {
Component parent = comp.getParent();
while(parent != null) {
if (parent.getAttribute(AD_WINDOW_ATTRIBUTE_KEY) != null) {
ADWindow adwindow = (ADWindow) parent.getAttribute(AD_WINDOW_ATTRIBUTE_KEY);
return adwindow;
}
parent = parent.getParent();
}
return null;
}
}

View File

@ -75,6 +75,7 @@ public class ADWindowContent extends AbstractADWindowContent
} else {
layout.setPage(page);
}
layout.setSpacing("0px");
//toolbar
Div north = new Div();

View File

@ -140,7 +140,9 @@ import org.zkoss.zul.Window.Mode;
public abstract class AbstractADWindowContent extends AbstractUIPart implements ToolbarListener,
EventListener<Event>, DataStatusListener, ActionListener
{
private static final CLogger logger;
private static final String ON_DEFER_SET_DETAILPANE_SELECTION_EVENT = "onDeferSetDetailpaneSelection";
private static final CLogger logger;
static
{
@ -213,6 +215,7 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements
Component comp = super.createPart(parent);
comp.addEventListener(LayoutUtils.ON_REDRAW_EVENT, this);
comp.addEventListener(ON_DEFER_SET_DETAILPANE_SELECTION_EVENT, this);
return comp;
}
@ -976,7 +979,7 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements
if (eventData != null && eventData instanceof Object[] && ((Object[])eventData).length == 2)
{
Object[] indexes = (Object[]) eventData;
int newTabIndex = (Integer)indexes[1];
final int newTabIndex = (Integer)indexes[1];
final int originalTabIndex = adTabbox.getSelectedIndex();
final int originalTabRow = adTabbox.getSelectedGridTab().getCurrentRow();
@ -986,7 +989,14 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements
public void onCallback(Boolean result) {
if (result)
{
adTabbox.setDetailpaneSelection(originalTabIndex, originalTabRow);
if (newTabIndex < originalTabIndex)
{
if (adTabbox.isDetailPaneLoaded())
adTabbox.setDetailPaneSelectedTab(originalTabIndex, originalTabRow);
else {
Events.echoEvent(new Event(ON_DEFER_SET_DETAILPANE_SELECTION_EVENT, getComponent(), new Integer[]{originalTabIndex, originalTabRow}));
}
}
}
else
{
@ -1027,6 +1037,10 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements
}
LayoutUtils.redraw((AbstractComponent) getComponent());
}
else if (event.getName().equals(ON_DEFER_SET_DETAILPANE_SELECTION_EVENT)) {
Integer[] data = (Integer[]) event.getData();
adTabbox.setDetailPaneSelectedTab(data[0], data[1]);
}
}
private void setActiveTab(final int newTabIndex, final Callback<Boolean> callback) {
@ -1099,10 +1113,10 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements
IADTabpanel newTabpanel = adTabbox.getSelectedTabpanel();
boolean activated = newTabpanel.isActive();
boolean activated = newTabpanel.isActivated();
if (oldTabpanel != null)
oldTabpanel.activate(false);
if (activated)
if (!activated)
newTabpanel.activate(true);
back = (newTabIndex < oldTabIndex);

View File

@ -28,6 +28,7 @@ import org.adempiere.webui.component.Tabpanel;
import org.adempiere.webui.component.ToolBar;
import org.adempiere.webui.component.ToolBarButton;
import org.adempiere.webui.component.Window;
import org.adempiere.webui.component.ZkCssHelper;
import org.adempiere.webui.event.ToolbarListener;
import org.adempiere.webui.window.WRecordInfo;
import org.compiere.model.DataStatusEvent;
@ -37,6 +38,7 @@ import org.compiere.util.Env;
import org.compiere.util.Msg;
import org.compiere.util.Util;
import org.zkoss.zhtml.Text;
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;
@ -62,6 +64,10 @@ import org.zkoss.zul.Space;
*/
public class BreadCrumb extends Div implements EventListener<Event> {
private static final String ON_MOUSE_OVER_ECHO_EVENT = "onMouseOverEcho";
private static final String ON_MOUSE_OUT_ECHO_EVENT = "onMouseOutEcho";
private static final String INFO_INDICATOR_IMAGE = "/images/InfoIndicator16.png";
private static final String ERROR_INDICATOR_IMAGE = "/images/ErrorIndicator16.png";
@ -160,12 +166,24 @@ public class BreadCrumb extends Div implements EventListener<Event> {
toolbar.setStyle("background-image: none; background-color: transparent; border: none;");
setWidgetAttribute(AdempiereWebUI.WIDGET_INSTANCE_NAME, "breadcrumb");
this.addEventListener(ON_MOUSE_OUT_ECHO_EVENT, this);
}
/**
*
* @param listener
*/
public void setToolbarListener(ToolbarListener listener) {
this.toolbarListener = listener;
}
/**
*
* @param label
* @param id
* @param clickable
*/
public void addPath(String label, String id, boolean clickable) {
if (clickable) {
BreadCrumbLink a = new BreadCrumbLink();
@ -193,6 +211,10 @@ public class BreadCrumb extends Div implements EventListener<Event> {
}
}
/**
*
* @return list of parent links
*/
public List<BreadCrumbLink> getParentLinks() {
List<BreadCrumbLink> parents = new ArrayList<BreadCrumbLink>();
for(Component component : layout.getChildren()) {
@ -202,20 +224,63 @@ public class BreadCrumb extends Div implements EventListener<Event> {
return parents;
}
/**
* add links to other tabs at the same level
* @param links
*/
public void addLinks(LinkedHashMap<String, String> links) {
this.links = links;
final Label pathLabel = (Label) layout.getChildren().get(layout.getChildren().size()-2);
pathLabel.setStyle("cursor: pointer; font-weight: bold");
pathLabel.setStyle("cursor: pointer; font-weight: bold; padding-right: 10px;");
EventListener<Event> listener = new EventListener<Event>() {
@Override
public void onEvent(Event event) throws Exception {
if (linkPopup != null ) {
if (linkPopup.getPage() != null && linkPopup.isVisible()) {
return;
if (linkPopup != null && linkPopup.getPage() != null && linkPopup.isVisible()) {
if (event.getName().equals(Events.ON_MOUSE_OUT)) {
linkPopup.setAttribute(ON_MOUSE_OUT_ECHO_EVENT, Boolean.TRUE);
StringBuilder script = new StringBuilder("setTimeout(function(){var w=zk('#")
.append(BreadCrumb.this.getUuid()).append("').$();")
.append("var e=new zk.Event(w, '")
.append(ON_MOUSE_OUT_ECHO_EVENT)
.append("', null, {toServer:true});")
.append("zAu.send(e);},500)");
final AuScript response = new AuScript(script.toString());
Clients.response(response);
}
return;
}
linkPopup = new Menupopup();
if (event.getName().equals(Events.ON_CLICK)) {
if (linkPopup != null && linkPopup.getPage() != null)
linkPopup.detach();
linkPopup = new Menupopup();
showLinksMenu(pathLabel);
} else if (event.getName().equals(Events.ON_MOUSE_OVER)) {
if (linkPopup == null || !linkPopup.isVisible()) {
if (linkPopup != null && linkPopup.getPage() != null)
linkPopup.detach();
linkPopup = new Menupopup();
StringBuilder script = new StringBuilder("setTimeout(function(){var w=zk('#")
.append(event.getTarget().getUuid()).append("').$();")
.append("var e=new zk.Event(w, '")
.append(ON_MOUSE_OVER_ECHO_EVENT)
.append("', null, {toServer:true});")
.append("zAu.send(e);},500)");
AuScript response = new AuScript(script.toString());
Clients.response(response);
}
} else if (event.getName().equals(Events.ON_MOUSE_OUT)) {
if (linkPopup != null && linkPopup.getPage() == null) {
linkPopup = null;
}
} else if (event.getName().equals(ON_MOUSE_OVER_ECHO_EVENT)) {
if (linkPopup != null && linkPopup.getPage() == null) {
showLinksMenu(pathLabel);
}
}
}
private void showLinksMenu(final Label pathLabel) {
for(Map.Entry<String, String>entry : BreadCrumb.this.links.entrySet()) {
final Menuitem item = new Menuitem();
item.setLabel(entry.getValue());
@ -223,12 +288,41 @@ public class BreadCrumb extends Div implements EventListener<Event> {
item.addEventListener(Events.ON_CLICK, BreadCrumb.this);
linkPopup.appendChild(item);
}
StringBuilder script = new StringBuilder("setTimeout(function(){var w=zk('#")
.append(BreadCrumb.this.getUuid()).append("').$();")
.append("var e=new zk.Event(w, '")
.append(ON_MOUSE_OUT_ECHO_EVENT)
.append("', null, {toServer:true});")
.append("zAu.send(e);},500)");
final AuScript response = new AuScript(script.toString());
linkPopup.addEventListener(Events.ON_MOUSE_OUT, new EventListener<Event>() {
@Override
public void onEvent(Event event) throws Exception {
if (linkPopup != null) {
linkPopup.setAttribute(ON_MOUSE_OUT_ECHO_EVENT, Boolean.TRUE);
Clients.response(response);
}
}
});
linkPopup.addEventListener(Events.ON_MOUSE_OVER, new EventListener<Event>() {
@Override
public void onEvent(Event event) throws Exception {
if (linkPopup != null && linkPopup.isVisible()) {
linkPopup.removeAttribute(ON_MOUSE_OUT_ECHO_EVENT);
}
}
});
linkPopup.setPage(pathLabel.getPage());
linkPopup.open(pathLabel);
}
};
pathLabel.addEventListener(Events.ON_CLICK, listener);
pathLabel.addEventListener(Events.ON_MOUSE_OVER, listener);
pathLabel.addEventListener(Events.ON_MOUSE_OUT, listener);
pathLabel.addEventListener(ON_MOUSE_OVER_ECHO_EVENT, listener);
ZkCssHelper.appendStyle(pathLabel, "background: transparent url('images/downarrow.png') no-repeat right center");
}
@Override
@ -241,10 +335,9 @@ public class BreadCrumb extends Div implements EventListener<Event> {
String title = Msg.getMsg(Env.getCtx(), "Who") + m_text;
new WRecordInfo (title, m_dse);
}else if(event.getTarget() instanceof RecordLink){
} else if(event.getTarget() instanceof RecordLink){
doZoom((RecordLink)event.getTarget());
}
else if (event.getTarget().getParent() == messageContainer) {
} else if (event.getTarget().getParent() == messageContainer) {
showPopup();
} else if (event.getTarget() == btnFirst) {
if (toolbarListener != null)
@ -258,23 +351,42 @@ public class BreadCrumb extends Div implements EventListener<Event> {
} else if (event.getTarget() == btnLast) {
if (toolbarListener != null)
toolbarListener.onLast();
} else if (event.getName().equals(ON_MOUSE_OUT_ECHO_EVENT)) {
if (linkPopup != null && linkPopup.getPage() != null && linkPopup.isVisible()
&& linkPopup.getAttribute(ON_MOUSE_OUT_ECHO_EVENT) != null) {
linkPopup.detach();
linkPopup = null;
}
} else {
Events.sendEvent(this, event);
}
}
/**
* remove all links
*/
public void reset() {
layout.getChildren().clear();
layout.appendChild(toolbarContainer);
this.links = null;
if (layout.getChildren().size() == 0 || layout.getChildren().size() > 1) {
layout.getChildren().clear();
layout.appendChild(toolbarContainer);
this.links = null;
}
}
/**
* enable/disable first record and previous record toolbar button
* @param enabled
*/
public void enableFirstNavigation(boolean enabled)
{
this.btnFirst.setDisabled(!enabled);
this.btnPrevious.setDisabled(!enabled);
}
/**
* enable or disable the next record and last record toolbar button
* @param enabled
*/
public void enableLastNavigation(boolean enabled)
{
this.btnLast.setDisabled(!enabled);
@ -505,7 +617,6 @@ public class BreadCrumb extends Div implements EventListener<Event> {
msgPopup.setContentStyle("overflow: auto");
msgPopup.setWidth("500px");
msgPopup.appendChild(msgPopupCnt);
// msgPopup.setPage(SessionManager.getAppDesktop().getComponent().getPage());
msgPopup.setShadow(true);
msgPopupCaption = new Caption();
msgPopup.appendChild(msgPopupCaption);
@ -524,10 +635,17 @@ public class BreadCrumb extends Div implements EventListener<Event> {
linkPopup.detach();
}
/**
*
* @param visible
*/
public void setNavigationToolbarVisibility(boolean visible) {
toolbarContainer.setVisible(visible);
}
/**
* @return true if there are one or more parent link
*/
public boolean hasParentLink() {
for(Component c : layout.getChildren()) {
if (c instanceof BreadCrumbLink) {
@ -537,6 +655,10 @@ public class BreadCrumb extends Div implements EventListener<Event> {
return false;
}
/**
*
* @return process logs
*/
public ProcessInfoLog[] getPLogs() {
return pInfoLogs;
}

View File

@ -21,6 +21,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.logging.Level;
import org.adempiere.util.Callback;
import org.adempiere.webui.component.ADTabListModel;
@ -54,10 +55,11 @@ import org.zkoss.zul.Vlayout;
*/
public class CompositeADTabbox extends AbstractADTabbox
{
private static final String ON_POST_TAB_SELECTION_CHANGED_EVENT = "onPostTabSelectionChanged";
public static final String ON_SELECTION_CHANGED_EVENT = "onSelectionChanged";
/** Logger */
@SuppressWarnings("unused")
private static CLogger log = CLogger.getCLogger (CompositeADTabbox.class);
private List<ADTabListModel.ADTabLabel> tabLabelList = new ArrayList<ADTabListModel.ADTabLabel>();
@ -66,17 +68,17 @@ public class CompositeADTabbox extends AbstractADTabbox
private Vlayout layout;
protected DetailPane detailPane;
private EventListener<Event> selectionListener;
private IADTabpanel headerTab;
private int selectedIndex = 0;
public CompositeADTabbox()
{
detailPane = new DetailPane();
public CompositeADTabbox(){
}
protected DetailPane createDetailPane() {
DetailPane detailPane = new DetailPane();
detailPane.setEventListener(new EventListener<Event>() {
@Override
@ -84,8 +86,8 @@ public class CompositeADTabbox extends AbstractADTabbox
if (DetailPane.ON_EDIT_EVENT.equals(event.getName())) {
if (headerTab.getGridTab().isNew()) return;
final int row = detailPane.getSelectedADTabpanel() != null
? detailPane.getSelectedADTabpanel().getGridTab().getCurrentRow()
final int row = getSelectedDetailADTabpanel() != null
? getSelectedDetailADTabpanel().getGridTab().getCurrentRow()
: 0;
final boolean formView = event.getData() != null ? (Boolean)event.getData() : true;
adWindowPanel.saveAndNavigate(new Callback<Boolean>() {
@ -99,8 +101,8 @@ public class CompositeADTabbox extends AbstractADTabbox
else if (DetailPane.ON_NEW_EVENT.equals(event.getName())) {
if (headerTab.getGridTab().isNew()) return;
final int row = detailPane.getSelectedADTabpanel() != null
? detailPane.getSelectedADTabpanel().getGridTab().getCurrentRow()
final int row = getSelectedDetailADTabpanel() != null
? getSelectedDetailADTabpanel().getGridTab().getCurrentRow()
: 0;
adWindowPanel.saveAndNavigate(new Callback<Boolean>() {
@Override
@ -116,7 +118,7 @@ public class CompositeADTabbox extends AbstractADTabbox
else if (DetailPane.ON_DELETE_EVENT.equals(event.getName())) {
if (headerTab.getGridTab().isNew()) return;
final IADTabpanel tabPanel = detailPane.getSelectedADTabpanel();
final IADTabpanel tabPanel = getSelectedDetailADTabpanel();
if (tabPanel != null && tabPanel.getGridTab().getRowCount() > 0
&& tabPanel.getGridTab().getCurrentRow() >= 0) {
FDialog.ask(tabPanel.getGridTab().getWindowNo(), null, "DeleteRecord?", new Callback<Boolean>() {
@ -135,11 +137,13 @@ public class CompositeADTabbox extends AbstractADTabbox
}
}
});
return detailPane;
}
protected void onEditDetail(int row, boolean formView) {
int oldIndex = selectedIndex;
IADTabpanel selectedPanel = detailPane.getSelectedADTabpanel();
IADTabpanel selectedPanel = getSelectedDetailADTabpanel();
if (selectedPanel == null) return;
int newIndex = selectedPanel.getTabNo();
@ -169,6 +173,13 @@ public class CompositeADTabbox extends AbstractADTabbox
layout.setPage(page);
}
layout.addEventListener(ON_POST_TAB_SELECTION_CHANGED_EVENT, new EventListener<Event>() {
@Override
public void onEvent(Event event) throws Exception {
onPostTabSelectionChanged();
}
});
BreadCrumb breadCrumb = getBreadCrumb();
breadCrumb.addEventListener(Events.ON_CLICK, new EventListener<Event>() {
@Override
@ -210,12 +221,10 @@ public class CompositeADTabbox extends AbstractADTabbox
return;
IADTabpanel tabPanel = (IADTabpanel) event.getTarget();
if (tabPanel == headerTab) {
if (tabPanel != headerTab) {
if (b != null && b.booleanValue()) {
activateDetailADTabpanel();
onActivateDetail(tabPanel);
}
} else {
onActivateDetail(tabPanel);
}
}
});
@ -225,26 +234,26 @@ public class CompositeADTabbox extends AbstractADTabbox
public void onEvent(Event event) throws Exception {
final IADTabpanel tabPanel = (IADTabpanel) event.getTarget();
int oldIndex = (Integer) event.getData();
if (oldIndex != detailPane.getSelectedIndex()) {
IADTabpanel prevTabPanel = detailPane.getADTabpanel(oldIndex);
if (oldIndex != headerTab.getDetailPane().getSelectedIndex()) {
IADTabpanel prevTabPanel = headerTab.getDetailPane().getADTabpanel(oldIndex);
if (prevTabPanel != null && prevTabPanel.needSave(true, true)) {
final int newIndex = detailPane.getSelectedIndex();
detailPane.setSelectedIndex(oldIndex);
final int newIndex = headerTab.getDetailPane().getSelectedIndex();
headerTab.getDetailPane().setSelectedIndex(oldIndex);
adWindowPanel.saveAndNavigate(new Callback<Boolean>() {
@Override
public void onCallback(Boolean result) {
if (result) {
detailPane.setSelectedIndex(newIndex);
onActivateDetail(tabPanel);
headerTab.getDetailPane().setSelectedIndex(newIndex);
tabPanel.activate(true);
}
}
});
} else {
detailPane.setSelectedIndex(detailPane.getSelectedIndex());
onActivateDetail(tabPanel);
headerTab.getDetailPane().setSelectedIndex(headerTab.getDetailPane().getSelectedIndex());
tabPanel.activate(true);
}
} else {
onActivateDetail(tabPanel);
tabPanel.activate(true);
}
}
});
@ -259,7 +268,8 @@ public class CompositeADTabbox extends AbstractADTabbox
if (detailPanel != null) {
detailPanel.setDetailPaneMode(true);
}
detailPane.setVflex("true");
if (headerTab.getDetailPane() != null)
headerTab.getDetailPane().setVflex("true");
}
}
});
@ -272,7 +282,7 @@ public class CompositeADTabbox extends AbstractADTabbox
if (tabPanel == headerTab) {
adWindowPanel.onToggle();
} else {
detailPane.onEdit(true);
headerTab.getDetailPane().onEdit(true);
}
}
@ -295,19 +305,18 @@ public class CompositeADTabbox extends AbstractADTabbox
headerTab = tabPanel;
updateBreadCrumb();
} else if (tabLabel.tabLevel <= 1) {
if (detailPane.getParent() == null) {
ADTabpanel adtabpanel = (ADTabpanel) headerTab;
adtabpanel.addDetails(detailPane);
if (headerTab.getDetailPane() == null) {
headerTab.setDetailPane(createDetailPane());
} else
tabPanel.setVisible(false);
detailPane.setHflex("1");
detailPane.addADTabpanel(tabPanel, tabLabel);
headerTab.getDetailPane().setHflex("1");
headerTab.getDetailPane().addADTabpanel(tabPanel, tabLabel);
tabPanel.setDetailPaneMode(true);
detailPane.setVflex("true");
headerTab.getDetailPane().setVflex("true");
} else {
detailPane.addADTabpanel(tabPanel, tabLabel, false);
headerTab.getDetailPane().addADTabpanel(tabPanel, tabLabel, false);
tabPanel.setDetailPaneMode(true);
detailPane.setVflex("true");
headerTab.getDetailPane().setVflex("true");
}
HtmlBasedComponent htmlComponent = (HtmlBasedComponent) tabPanel;
htmlComponent.setVflex("1");
@ -316,39 +325,33 @@ public class CompositeADTabbox extends AbstractADTabbox
tabPanel.getGridTab().addDataStatusListener(new SyncDataStatusListener(tabPanel));
}
private void activateDetailADTabpanel() {
if (detailPane != null && detailPane.getParent() != null) {
IADTabpanel tabPanel = detailPane.getSelectedADTabpanel();
if (tabPanel != null) {
tabPanel.activate(true);
if (!tabPanel.isGridView()) {
tabPanel.switchRowPresentation();
}
}
private void activateDetailIfVisible() {
if (headerTab instanceof ADTabpanel) {
((ADTabpanel)headerTab).activateDetailIfVisible();
}
}
@Override
protected void updateTabState() {
if (detailPane != null && detailPane.getTabcount() > 0)
if (isDetailPaneLoaded())
{
for(int i = 0; i < detailPane.getTabcount(); i++)
for(int i = 0; i < headerTab.getDetailPane().getTabcount(); i++)
{
IADTabpanel adtab = detailPane.getADTabpanel(i);
IADTabpanel adtab = headerTab.getDetailPane().getADTabpanel(i);
if (adtab.getDisplayLogic() != null && adtab.getDisplayLogic().trim().length() > 0) {
if (!Evaluator.evaluateLogic(headerTab, adtab.getDisplayLogic())) {
detailPane.setTabVisibility(i, false);
headerTab.getDetailPane().setTabVisibility(i, false);
} else {
detailPane.setTabVisibility(i, true);
headerTab.getDetailPane().setTabVisibility(i, true);
}
}
}
int selected = detailPane.getSelectedIndex();
if (detailPane.getADTabpanel(selected) == null || !detailPane.isTabVisible(selected)) {
for(int i = 0; i < detailPane.getTabcount(); i++) {
int selected = headerTab.getDetailPane().getSelectedIndex();
if (headerTab.getDetailPane().getADTabpanel(selected) == null || !headerTab.getDetailPane().isTabVisible(selected)) {
for(int i = 0; i < headerTab.getDetailPane().getTabcount(); i++) {
if (selected == i) continue;
if (detailPane.isTabVisible(i)) {
detailPane.setSelectedIndex(i);
if (headerTab.getDetailPane().isTabVisible(i)) {
headerTab.getDetailPane().setSelectedIndex(i);
break;
}
}
@ -387,46 +390,68 @@ public class CompositeADTabbox extends AbstractADTabbox
layout.getChildren().clear();
layout.appendChild(headerTab);
detailPane.detach();
detailPane.reset();
int currentLevel = headerTab.getTabLevel();
for (int i = selectedIndex + 1; i< tabPanelList.size(); i++) {
IADTabpanel tabPanel = tabPanelList.get(i);
int tabLevel = tabPanel.getTabLevel();
ADTabListModel.ADTabLabel tabLabel = tabLabelList.get(i);
if ((tabLevel - currentLevel) == 1 || (tabLevel == 0 && currentLevel == 0)) {
if (tabPanel.isActive() && !tabPanel.isGridView()) {
tabPanel.switchRowPresentation();
}
if (tabPanel.getParent() != null) tabPanel.detach();
detailPane.addADTabpanel(tabPanel, tabLabel);
tabPanel.setDetailPaneMode(true);
} else if (tabLevel > currentLevel ){
detailPane.addADTabpanel(tabPanel, tabLabel, false);
tabPanel.setDetailPaneMode(true);
} else {
break;
}
}
if (detailPane.getTabcount() > 0 && !headerTab.getGridTab().isSortTab()) {
ADTabpanel adtabpanel = (ADTabpanel) headerTab;
adtabpanel.addDetails(detailPane);
detailPane.setVflex("true");
detailPane.setSelectedIndex(0);
activateDetailADTabpanel();
}
//set state
headerTab.setDetailPaneMode(false);
getBreadCrumb().getFirstChild().setVisible(false);
Events.echoEvent(new Event(ON_POST_TAB_SELECTION_CHANGED_EVENT, layout));
}
private void onPostTabSelectionChanged() {
if (headerTab instanceof ADTabpanel) {
DetailPane detailPane = headerTab.getDetailPane();
if (detailPane == null) {
detailPane = createDetailPane();
}
int tabIndex = -1;
int currentLevel = headerTab.getTabLevel();
for (int i = selectedIndex + 1; i< tabPanelList.size(); i++) {
IADTabpanel tabPanel = tabPanelList.get(i);
int tabLevel = tabPanel.getTabLevel();
ADTabListModel.ADTabLabel tabLabel = tabLabelList.get(i);
if ((tabLevel - currentLevel) == 1 || (tabLevel == 0 && currentLevel == 0)) {
if (tabPanel.isActivated() && !tabPanel.isGridView()) {
tabPanel.switchRowPresentation();
}
if (tabPanel.getParent() != null) tabPanel.detach();
tabIndex++;
detailPane.setADTabpanel(tabIndex, tabPanel, tabLabel);
tabPanel.setDetailPaneMode(true);
} else if (tabLevel > currentLevel ){
tabIndex++;
detailPane.setADTabpanel(tabIndex, tabPanel, tabLabel, false);
tabPanel.setDetailPaneMode(true);
} else {
break;
}
}
if (detailPane.getTabcount() > 0 && !headerTab.getGridTab().isSortTab()) {
detailPane.setVflex("true");
detailPane.setSelectedIndex(0);
if (headerTab.getDetailPane() == null) {
headerTab.setDetailPane(detailPane);
}
activateDetailIfVisible();
}
}
updateBreadCrumb();
getBreadCrumb().getFirstChild().setVisible(true);
updateTabState();
ADWindow adwindow = ADWindow.findADWindow(layout);
if (adwindow != null) {
adwindow.getADWindowContent().getToolbar().enableTabNavigation(getBreadCrumb().hasParentLink(),
headerTab.getDetailPane() != null && headerTab.getDetailPane().getTabcount() > 0);
}
}
private void updateBreadCrumb() {
BreadCrumb breadCrumb = getBreadCrumb();
breadCrumb.reset();
if (selectedIndex > 0) {
List<ADTabLabel> parents = new ArrayList<ADTabListModel.ADTabLabel>();
List<Integer> parentIndex = new ArrayList<Integer>();
@ -510,14 +535,15 @@ public class CompositeADTabbox extends AbstractADTabbox
Execution execution = Executions.getCurrent();
if (execution == null) return;
if (tabPanel == headerTab && detailPane.getPage() != null && e.getChangedColumn() == -1) {
if (tabPanel == headerTab && e.getChangedColumn() == -1
&& isDetailActivated()) {
ArrayList<String> parentColumnNames = new ArrayList<String>();
GridField[] parentFields = headerTab.getGridTab().getFields();
for (GridField parentField : parentFields) {
parentColumnNames.add(parentField.getColumnName());
}
IADTabpanel detailTab = detailPane.getSelectedADTabpanel();
IADTabpanel detailTab = getSelectedDetailADTabpanel();
if (detailTab != null) {
//check data action
String uuid = (String) execution.getAttribute(CompositeADTabbox.class.getName()+".dataAction");
@ -540,7 +566,7 @@ public class CompositeADTabbox extends AbstractADTabbox
detailTab.activate(true);
detailTab.setDetailPaneMode(true);
}
detailPane.setVflex("true");
headerTab.getDetailPane().setVflex("true");
}
}
@ -548,13 +574,24 @@ public class CompositeADTabbox extends AbstractADTabbox
@Override
public void onDetailRecord() {
if (detailPane != null && detailPane.getSelectedADTabpanel() != null) {
if (headerTab.getDetailPane() != null && getSelectedDetailADTabpanel() != null) {
try {
detailPane.onEdit(false);
} catch (Exception e) {}
headerTab.getDetailPane().onEdit(false);
} catch (Exception e) {
log.log(Level.SEVERE, e.getLocalizedMessage(), e);
}
}
}
public boolean isDetailActivated() {
if (headerTab instanceof ADTabpanel) {
ADTabpanel atp = (ADTabpanel) headerTab;
return atp.hasDetailTabs() && getSelectedDetailADTabpanel() != null &&
getSelectedDetailADTabpanel().isActivated();
}
return false;
}
@Override
public boolean isSortTab() {
return headerTab != null ? headerTab.getGridTab().isSortTab() : false;
@ -562,8 +599,8 @@ public class CompositeADTabbox extends AbstractADTabbox
@Override
public IADTabpanel getSelectedDetailADTabpanel() {
if (detailPane != null && detailPane.getParent() != null) {
return detailPane.getSelectedADTabpanel();
if (headerTab instanceof ADTabpanel && ((ADTabpanel)headerTab).hasDetailTabs()) {
return headerTab.getDetailPane().getSelectedADTabpanel();
}
return null;
}
@ -612,7 +649,7 @@ public class CompositeADTabbox extends AbstractADTabbox
@Override
public void setDetailPaneStatusMessage(String status, boolean error) {
detailPane.setStatusMessage(status, error);
headerTab.getDetailPane().setStatusMessage(status, error);
}
@Override
@ -636,9 +673,9 @@ public class CompositeADTabbox extends AbstractADTabbox
tabPanel.switchRowPresentation();
}
tabPanel.setDetailPaneMode(true);
detailPane.setVflex("true");
headerTab.getDetailPane().setVflex("true");
if (tabPanel instanceof ADSortTab) {
detailPane.updateToolbar(false, true);
headerTab.getDetailPane().updateToolbar(false, true);
} else {
tabPanel.dynamicDisplay(0);
}
@ -648,7 +685,7 @@ public class CompositeADTabbox extends AbstractADTabbox
String msg = CLogger.retrieveErrorString(null);
if (msg != null)
{
detailPane.setStatusMessage(Msg.getMsg(Env.getCtx(), msg), true);
headerTab.getDetailPane().setStatusMessage(Msg.getMsg(Env.getCtx(), msg), true);
}
//other error will be catch in the dataStatusChanged event
}
@ -656,24 +693,36 @@ public class CompositeADTabbox extends AbstractADTabbox
@Override
public void updateDetailPaneToolbar(boolean changed, boolean readOnly) {
if (headerTab.getGridTab().isNew() || headerTab.getGridTab().getRowCount() == 0)
detailPane.disableToolbar();
headerTab.getDetailPane().disableToolbar();
else
detailPane.updateToolbar(changed, readOnly);
headerTab.getDetailPane().updateToolbar(changed, readOnly);
}
@Override
public void setDetailpaneSelection(int tabIndex, int currentRow) {
if (detailPane.getTabcount() > 0) {
for(int i = 0; i < detailPane.getTabcount(); i++) {
IADTabpanel adtab = detailPane.getADTabpanel(i);
int index = adtab.getTabNo();
if (index == tabIndex) {
if (!detailPane.isTabVisible(i) || !detailPane.isTabEnabled(i)) {
public boolean isDetailPaneLoaded() {
if (headerTab.getDetailPane() == null || headerTab.getDetailPane().getTabcount() == 0)
return false;
for(int i = 0; i < headerTab.getDetailPane().getTabcount(); i++) {
if (headerTab.getDetailPane().getADTabpanel(i) == null)
return false;
}
return true;
}
@Override
public void setDetailPaneSelectedTab(int adTabNo, int currentRow) {
if (headerTab instanceof ADTabpanel && ((ADTabpanel) headerTab).hasDetailTabs()) {
for(int i = 0; i < headerTab.getDetailPane().getTabcount(); i++) {
IADTabpanel adtab = headerTab.getDetailPane().getADTabpanel(i);
if (adtab == null) continue;
int tabNo = adtab.getTabNo();
if (tabNo == adTabNo) {
if (!headerTab.getDetailPane().isTabVisible(i) || !headerTab.getDetailPane().isTabEnabled(i)) {
return;
}
if (i != detailPane.getSelectedIndex()) {
detailPane.setSelectedIndex(i);
detailPane.fireActivateDetailEvent();
if (i != headerTab.getDetailPane().getSelectedIndex()) {
headerTab.getDetailPane().setSelectedIndex(i);
headerTab.getDetailPane().fireActivateDetailEvent();
}
if (adtab.getGridTab().getCurrentRow() != currentRow)
adtab.getGridTab().setCurrentRow(currentRow, true);

View File

@ -114,15 +114,25 @@ public class DetailPane extends Panel implements EventListener<Event>, IdSpace {
setId("detailPane");
}
/**
* @return selected tab index
*/
public int getSelectedIndex() {
return tabbox.getSelectedIndex();
}
/**
* set selected tab index
* @param curTabIndex
*/
public void setSelectedIndex(int curTabIndex) {
tabbox.setSelectedIndex(curTabIndex);
prevSelectedIndex = curTabIndex;
}
/**
* @return number of tabs
*/
public int getTabcount() {
int count = 0;
Tabs tabs = tabbox.getTabs();
@ -131,18 +141,64 @@ public class DetailPane extends Panel implements EventListener<Event>, IdSpace {
return count;
}
/**
* undo last tab selection
*/
public void undoLastTabSelection() {
tabbox.setSelectedIndex(prevSelectedIndex);
}
/**
* redraw tabbox
*/
public void refresh() {
tabbox.invalidate();
}
/**
* replace of add
* @param index
* @param tabPanel
* @param tabLabel
*/
public void setADTabpanel(int index, IADTabpanel tabPanel, ADTabLabel tabLabel) {
if (index < getTabcount()) {
tabbox.getTabpanel(index).appendChild(tabPanel);
} else {
addADTabpanel(tabPanel, tabLabel);
}
}
/**
* replace or add
* @param index
* @param tabPanel
* @param tabLabel
* @param enabled
*/
public void setADTabpanel(int index, IADTabpanel tabPanel, ADTabLabel tabLabel, boolean enabled) {
if (index < getTabcount()) {
tabbox.getTabpanel(index).appendChild(tabPanel);
} else {
addADTabpanel(tabPanel, tabLabel, enabled);
}
}
/**
*
* @param tabPanel
* @param tabLabel
*/
public void addADTabpanel(IADTabpanel tabPanel, ADTabLabel tabLabel) {
addADTabpanel(tabPanel, tabLabel, true);
}
/**
*
* @param tabPanel
* @param tabLabel
* @param enabled
*/
public void addADTabpanel(IADTabpanel tabPanel, ADTabLabel tabLabel, boolean enabled) {
Tabs tabs = tabbox.getTabs();
if (tabs == null) {
@ -280,10 +336,17 @@ public class DetailPane extends Panel implements EventListener<Event>, IdSpace {
LayoutUtils.openPopupWindow(button, popup, "after_start");
}
/**
*
* @param listener
*/
public void setEventListener(EventListener<Event> listener) {
eventListener = listener;
}
/**
* remove all tabs and tabpanels
*/
public void reset() {
if (tabbox.getTabs() != null) {
tabbox.getTabs().getChildren().clear();
@ -294,6 +357,10 @@ public class DetailPane extends Panel implements EventListener<Event>, IdSpace {
}
/**
* @param index
* @return adtabpanel at index
*/
public IADTabpanel getADTabpanel(int index) {
if (index < 0 || index >= tabbox.getTabpanels().getChildren().size())
return null;
@ -306,6 +373,10 @@ public class DetailPane extends Panel implements EventListener<Event>, IdSpace {
return null;
}
/**
*
* @return selected adtabpanel
*/
public IADTabpanel getSelectedADTabpanel() {
org.zkoss.zul.Tabpanel selectedPanel = tabbox.getSelectedPanel();
if (selectedPanel != null) {
@ -317,6 +388,11 @@ public class DetailPane extends Panel implements EventListener<Event>, IdSpace {
return null;
}
/**
*
* @param status
* @param error
*/
public void setStatusMessage(String status, boolean error) {
IADTabpanel tabPanel = getSelectedADTabpanel();
if (tabPanel == null) return;
@ -404,7 +480,8 @@ public class DetailPane extends Panel implements EventListener<Event>, IdSpace {
createPopupContent(status);
showPopup(error, messageContainer);
} else if (event.getName().equals(ADTabpanel.ON_DYNAMIC_DISPLAY_EVENT)) {
updateProcessToolbar();
if (LayoutUtils.isReallyVisible(this))
updateProcessToolbar();
} else if (event.getName().equals(LayoutUtils.ON_REDRAW_EVENT)) {
ExecutionCtrl ctrl = (ExecutionCtrl) Executions.getCurrent();
Event evt = ctrl.getNextEvent();
@ -463,6 +540,11 @@ public class DetailPane extends Panel implements EventListener<Event>, IdSpace {
tabbox.setVflex(flex);
}
/**
* update toolbar button state
* @param changed
* @param readOnly
*/
public void updateToolbar(boolean changed, boolean readOnly) {
int index = getSelectedIndex();
if (index < 0 || index >= getTabcount()) return;
@ -503,6 +585,7 @@ public class DetailPane extends Panel implements EventListener<Event>, IdSpace {
Toolbar toolbar = (Toolbar) tabpanel.getFirstChild();
IADTabpanel adtab = getADTabpanel(index);
if (adtab == null) return;
for(Component c : toolbar.getChildren()) {
if (c instanceof ToolBarButton) {
@ -519,11 +602,19 @@ public class DetailPane extends Panel implements EventListener<Event>, IdSpace {
}
}
/**
* Edit current record
* @param formView
* @throws Exception
*/
public void onEdit(boolean formView) throws Exception {
Event openEvent = new Event(ON_EDIT_EVENT, DetailPane.this, Boolean.valueOf(formView));
eventListener.onEvent(openEvent);
}
/**
* fire the on activate detail event
*/
public void fireActivateDetailEvent() {
int index = tabbox.getSelectedIndex();
IADTabpanel tabPanel = (IADTabpanel) tabbox.getTabpanel(index).getChildren().get(1);
@ -531,11 +622,15 @@ public class DetailPane extends Panel implements EventListener<Event>, IdSpace {
Events.sendEvent(activateEvent);
}
public void setTabVisibility(int i, boolean visible) {
if (i < 0 || tabbox.getTabs() == null || i >= tabbox.getTabs().getChildren().size())
/**
* @param tabIndex
* @param visible
*/
public void setTabVisibility(int tabIndex, boolean visible) {
if (tabIndex < 0 || tabbox.getTabs() == null || tabIndex >= tabbox.getTabs().getChildren().size())
return;
Tab tab = (Tab) tabbox.getTabs().getChildren().get(i);
Tab tab = (Tab) tabbox.getTabs().getChildren().get(tabIndex);
tab.setVisible(visible);
if (tab.isSelected()) {
tab.setSelected(false);
@ -545,29 +640,46 @@ public class DetailPane extends Panel implements EventListener<Event>, IdSpace {
}
}
public boolean isTabVisible(int i) {
if (i < 0 || tabbox.getTabs() == null || i >= tabbox.getTabs().getChildren().size())
/**
*
* @param tabIndex
* @return true if tab at tabIndex is visible
*/
public boolean isTabVisible(int tabIndex) {
if (tabIndex < 0 || tabbox.getTabs() == null || tabIndex >= tabbox.getTabs().getChildren().size())
return false;
return tabbox.getTabs().getChildren().get(i).isVisible();
return tabbox.getTabs().getChildren().get(tabIndex).isVisible();
}
public boolean isTabEnabled(int i) {
if (i < 0 || tabbox.getTabs() == null || i >= tabbox.getTabs().getChildren().size())
/**
* @param tabIndex
* @return true if tab at tabIndex is enable
*/
public boolean isTabEnabled(int tabIndex) {
if (tabIndex < 0 || tabbox.getTabs() == null || tabIndex >= tabbox.getTabs().getChildren().size())
return false;
Tab tab = (Tab) tabbox.getTabs().getChildren().get(i);
Tab tab = (Tab) tabbox.getTabs().getChildren().get(tabIndex);
return !tab.isDisabled();
}
public void setTabEnabled(int i, boolean enabled) {
if (i < 0 || tabbox.getTabs() == null || i >= tabbox.getTabs().getChildren().size())
/**
*
* @param tabIndex
* @param enabled
*/
public void setTabEnabled(int tabIndex, boolean enabled) {
if (tabIndex < 0 || tabbox.getTabs() == null || tabIndex >= tabbox.getTabs().getChildren().size())
return;
Tab tab = (Tab) tabbox.getTabs().getChildren().get(i);
Tab tab = (Tab) tabbox.getTabs().getChildren().get(tabIndex);
tab.setDisabled(!enabled);
}
/**
* disable toolbar
*/
public void disableToolbar() {
int index = getSelectedIndex();
if (index < 0 || index >= getTabcount()) return;

View File

@ -109,25 +109,72 @@ public interface IADTabbox extends UIPart {
*/
public void setADWindowPanel(AbstractADWindowContent abstractADWindowPanel);
/**
* drill down to the current selected adtabpanel
*/
public void onDetailRecord();
/**
* @return true if current header tab is a sort tab
*/
public boolean isSortTab();
/**
* @param rowChange
* @param onlyRealChange
* @return true if there are changes pending to be save
*/
public boolean needSave(boolean rowChange, boolean onlyRealChange);
/**
* ignore all pending changes
*/
public void dataIgnore();
/**
* @return selected header grid tab
*/
public GridTab getSelectedGridTab();
/**
*
* @param onSaveEvent
* @return true if save is successfull
*/
public boolean dataSave(boolean onSaveEvent);
/**
*
* @param status
* @param error
*/
public void setDetailPaneStatusMessage(String status, boolean error);
/**
* @return the currently selected detail adtabpanel
*/
IADTabpanel getSelectedDetailADTabpanel();
/**
* @return dirty adtabpanel that need save ( if any )
*/
IADTabpanel getDirtyADTabpanel();
/**
*
* @param changed
* @param readOnly
*/
public void updateDetailPaneToolbar(boolean changed, boolean readOnly);
public void setDetailpaneSelection(int tabIndex, int currentRow);
/**
* @param tabIndex
* @param currentRow
*/
public void setDetailPaneSelectedTab(int tabIndex, int currentRow);
/**
* @return true if all the tabs of detail pane have been linked up with adtabpanel
*/
boolean isDetailPaneLoaded();
}

View File

@ -120,19 +120,64 @@ public interface IADTabpanel extends Component, Evaluatee {
*/
public boolean isGridView();
public boolean isActive();
/**
* @return true if the panel have been activated
*/
public boolean isActivated();
/**
*
* @param detailMode
*/
public void setDetailPaneMode(boolean detailMode);
/**
*
* @return true if the panel is in detailpane node
*/
public boolean isDetailPaneMode();
/**
*
* @return gridview instance
*/
public abstract GridView getGridView();
/**
*
* @param rowChange
* @param onlyRealChange
* @return true if there are pending changes
*/
public boolean needSave(boolean rowChange, boolean onlyRealChange);
/**
* @param onSaveEvent
* @return true if the save operation completed successfully
*/
public boolean dataSave(boolean onSaveEvent);
/**
*
* @param tabNo
*/
public void setTabNo(int tabNo);
/**
*
* @return tab no ( ad_tab.tabno )
*/
public int getTabNo();
/**
*
* @param detailPane
*/
public void setDetailPane(DetailPane detailPane);
/**
*
* @return detailpane
*/
public DetailPane getDetailPane();
}

View File

@ -488,6 +488,7 @@ div.wc-modal, div.wc-modal-none, div.wc-highlighted, div.wc-highlighted-none {
border: none;
width: 100%;
height: 100%;
background-color: #F9F9F9;
}
.adwindow-layout .z-center {
@ -577,10 +578,12 @@ div.wc-modal, div.wc-modal-none, div.wc-highlighted, div.wc-highlighted-none {
.adwindow-gridview-detail + .z-south-splt {
border-top: 1px solid #C5C5C5;
border-bottom: 1px solid #C5C5C5;
}
.adwindow-gridview-detail .z-south-body {
padding-top: 1px;
background-color: #D3D3D3;
}
.adwindow-gridview-borderlayout {
@ -807,6 +810,12 @@ tr.z-group {
font-family: Helvetica,Arial,sans-serif;
}
.z-group td.z-group-inner {
overflow: hidden !important;
border-bottom: 1px solid #CFCFCF !important;
border-top: 1px solid #CFCFCF !important;
}
<%-- Tablet --%>
.tablet-scrolling {
-webkit-overflow-scrolling: touch;
@ -1043,12 +1052,6 @@ tbody.z-grid-empty-body td {
width: 85% !important;
}
.z-group td.z-group-inner {
overflow: hidden !important;
border-bottom: 1px solid #CFCFCF !important;
border-top: 1px solid #CFCFCF !important;
}
.embedded-dialog {
position: absolute;
}