diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/component/Tab.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/component/Tab.java index b9335bb5ef..30f383e3ea 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/component/Tab.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/component/Tab.java @@ -151,8 +151,12 @@ public class Tab extends org.zkoss.zul.Tab //Cache panel before detach , or we couldn't get it after tab is detached. final org.zkoss.zul.Tabpanel panel = getLinkedPanel(); - detach(); + if (getTabbox() instanceof Tabbox) { + ((Tabbox)getTabbox()).removeTabFromActiveSeq(this); + } + detach(); + if (panel != null) { // B60-ZK-1160: Exception when closing tab with included content // Must clean up included content before detaching tab panel @@ -170,6 +174,19 @@ public class Tab extends org.zkoss.zul.Tab * @return */ protected org.zkoss.zul.Tab selectNextTabWR() { + Tabbox idTabbox = null; + if (getTabbox() instanceof Tabbox) { + idTabbox = (Tabbox)getTabbox(); + } + + if (idTabbox != null && idTabbox.isActiveBySeq()) { + org.zkoss.zul.Tab nextActiveTab = idTabbox.getNextActiveBySeq(); + if (nextActiveTab != null) { + nextActiveTab.setSelected(true); + return nextActiveTab; + } + } + for (org.zkoss.zul.Tab tab = (org.zkoss.zul.Tab) getPreviousSibling(); tab != null; tab = (org.zkoss.zul.Tab) tab.getPreviousSibling()) if (!tab.isDisabled()) { tab.setSelected(true); diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/component/Tabbox.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/component/Tabbox.java index 81d82dcc9d..ac897af16b 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/component/Tabbox.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/component/Tabbox.java @@ -17,10 +17,18 @@ package org.adempiere.webui.component; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.Iterator; + 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.SelectEvent; import org.zkoss.zul.Tab; import org.zkoss.zul.Tabpanels; +import org.zkoss.zul.Tabs; /** * @@ -28,7 +36,7 @@ import org.zkoss.zul.Tabpanels; * @date Feb 25, 2007 * @version $Revision: 0.10 $ */ -public class Tabbox extends org.zkoss.zul.Tabbox +public class Tabbox extends org.zkoss.zul.Tabbox implements EventListener { /** @@ -36,6 +44,13 @@ public class Tabbox extends org.zkoss.zul.Tabbox */ private static final long serialVersionUID = 1400484283064851775L; private boolean isSupportTabDragDrop = false; + private boolean isActiveBySeq = false; + + private Deque activeTabSeq = new ArrayDeque<>(); + public Tabbox () { + super(); + this.addEventListener(Events.ON_SELECT, this); + } public Tabpanel getTabpanel(int index) { @@ -80,4 +95,72 @@ public class Tabbox extends org.zkoss.zul.Tabbox super.onPageDetached(page); Events.sendEvent("onPageDetached", this, null); } + + /** + * add current selected tab to stack when a new tab is selected + */ + @Override + public void onEvent(Event event) throws Exception { + if (event instanceof SelectEvent && isActiveBySeq()) { + @SuppressWarnings("rawtypes") + SelectEvent selectEvent = (SelectEvent)event; + @SuppressWarnings("rawtypes") + Iterator itPrevSelectedTab = selectEvent.getPreviousSelectedItems().iterator(); + if (itPrevSelectedTab.hasNext()) { + activeTabSeq.push((Tab)itPrevSelectedTab.next()); + } + + } + + } + + /** + * override to add active tab to stack when tab is selected by add to {@link Tabs} + */ + @Override + public void setSelectedTab(Tab tab) { + if (getSelectedTab() != null) { + activeTabSeq.push(getSelectedTab()); + } + super.setSelectedTab(tab); + } + + public boolean isActiveBySeq() { + return isActiveBySeq; + } + + public void setActiveBySeq(boolean isActiveBySeq) { + this.isActiveBySeq = isActiveBySeq; + } + + /** + * select next active tab by order store on stack folow FILO + * @return + */ + public Tab getNextActiveBySeq () { + Tab cadidateTabActive = null; + while ((cadidateTabActive = activeTabSeq.peek()) != null) { + boolean canNotActive = cadidateTabActive.isDisabled() || !cadidateTabActive.isVisible(); + if (canNotActive) { + // move disable item to last stack it can be active late + cadidateTabActive = activeTabSeq.pop(); + activeTabSeq.addLast(cadidateTabActive); + }else if (cadidateTabActive.getParent() == null) { + activeTabSeq.pop();// this tab is close by code or by close at unselected state so just remove it from stack + }else { + return activeTabSeq.pop(); + } + } + + return null; + } + + /** + * activeTabSeq is maintain by selected tab event, so when close by code or close on unselected state should call this function to save memory
+ * in case don't call it, it still manage from {@link #getNextActiveBySeq()} + * @param closeTab + */ + public void removeTabFromActiveSeq (Tab closeTab) { + activeTabSeq.remove(closeTab); + } } diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/part/WindowContainer.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/part/WindowContainer.java index 31be322d96..f1f3191e83 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/part/WindowContainer.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/part/WindowContainer.java @@ -77,6 +77,7 @@ public class WindowContainer extends AbstractUIPart implements EventListener