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 a597848a73..8bc88bfb32 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,6 +17,7 @@
package org.adempiere.webui.component;
+import org.zkoss.zul.Tab;
import org.zkoss.zul.Tabpanels;
/**
@@ -27,11 +28,13 @@ import org.zkoss.zul.Tabpanels;
*/
public class Tabbox extends org.zkoss.zul.Tabbox
{
- /**
+
+ /**
*
*/
- private static final long serialVersionUID = 8453423102898624801L;
-
+ private static final long serialVersionUID = 1400484283064851775L;
+ private boolean isSupportTabDragDrop;
+
public Tabpanel getTabpanel(int index)
{
try
@@ -49,5 +52,18 @@ public class Tabbox extends org.zkoss.zul.Tabbox
public Tabpanel getSelectedTabpanel()
{
return getTabpanel(this.getSelectedIndex());
- }
+ }
+
+ public boolean isSupportTabDragDrop() {
+ return isSupportTabDragDrop;
+ }
+
+ /**
+ * let support drag&drop {@link Tab}
+ * @param isSupportTabDragDrop
+ */
+ public void setSupportTabDragDrop(boolean isSupportTabDragDrop) {
+ this.isSupportTabDragDrop = isSupportTabDragDrop;
+ }
+
}
diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/component/Tabs.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/component/Tabs.java
index e2b428d8f0..31597846d7 100644
--- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/component/Tabs.java
+++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/component/Tabs.java
@@ -17,21 +17,163 @@
package org.adempiere.webui.component;
+import java.util.Iterator;
+
+import org.zkoss.zk.ui.Component;
+import org.zkoss.zk.ui.event.DropEvent;
+import org.zkoss.zk.ui.event.Event;
+import org.zkoss.zk.ui.event.EventListener;
+import org.zkoss.zk.ui.event.Events;
+import org.zkoss.zul.Tab;
+import org.zkoss.zul.Tabpanels;
+
/**
*
* @author Ashley G Ramdass
* @date Mar 2, 2007
* @version $Revision: 0.10 $
*/
-public class Tabs extends org.zkoss.zul.Tabs
+public class Tabs extends org.zkoss.zul.Tabs implements EventListener
{
- /**
+
+ /**
*
*/
- private static final long serialVersionUID = -2416323107841662771L;
+ private static final long serialVersionUID = 4939779587719677815L;
public Tabs()
{
super();
}
+
+ /**
+ * override to set drag/drop for {@link Tab} already add to {@link Tabs} before {@link Tabs} add to {@link Tabbox}
+ */
+ @Override
+ public void setParent(Component parent) {
+ super.setParent(parent);
+ if (parent == null || !(parent instanceof Tabbox)) {
+ return;
+ }
+
+ Tabbox tabBox = (Tabbox)parent;
+
+ // set drag/drop for tab already added to tabs
+ for (Iterator it = getChildren().iterator(); it.hasNext();) {
+ final Tab tabAdded = (Tab) it.next();
+ if (tabBox.isSupportTabDragDrop()) {
+ setDragDropTab(tabAdded);
+ }else {
+ unsetDragDropTab(tabAdded);
+ }
+ }
+
+ // handle drop tab to tabs (end of tabs)
+ if (tabBox.isSupportTabDragDrop()) {
+ this.addEventListener(Events.ON_DROP, this);
+ this.setDroppable(Boolean.TRUE.toString());
+ }else {
+ this.removeEventListener(Events.ON_DROP, this);
+ this.setDroppable(Boolean.FALSE.toString());
+ }
+
+ }
+
+ /**
+ * override to set drag|drop for tab depends on {@link Tabbox#isSupportTabDragDrop()}
+ */
+ @Override
+ public void onChildAdded(Component child) {
+ super.onChildAdded(child);
+ if (getTabbox() != null && getTabbox() instanceof Tabbox) {
+ Tabbox tabbox = (Tabbox)getTabbox();
+ if (child instanceof org.zkoss.zul.Tab && tabbox.isSupportTabDragDrop()) {
+ org.zkoss.zul.Tab tab = (org.zkoss.zul.Tab)child;
+ setDragDropTab(tab);
+ }
+ }
+ }
+
+ /**
+ * setup {@link Tab} to support drag|drop
+ * @param tab
+ */
+ protected void setDragDropTab (org.zkoss.zul.Tab tab){
+ tab.setDraggable("true");
+ tab.setDroppable("true");
+ //set org.zkoss.zk.ui.EventListener.duplicateIgnored=true, so don't worry about duplicate handle
+ tab.addEventListener(Events.ON_DROP, this);
+ }
+
+ /**
+ * setup {@link Tab} to un-support drag|drop
+ * @param tab
+ */
+ protected void unsetDragDropTab (org.zkoss.zul.Tab tab){
+ tab.setDraggable("false");
+ tab.setDroppable("false");
+ tab.removeEventListener(Events.ON_DROP, this);
+ }
+
+ /**
+ * handle when user drop tab
+ */
+ @Override
+ public void onEvent(Event event) throws Exception {
+ if (event != null && event instanceof DropEvent) {
+ dragDropTab((DropEvent)event);
+ }
+ }
+
+ /**
+ * implement handle drop a {@link Tab} to other {@link Tab} or {@link Tabs}
+ * @param dropEvent
+ */
+ protected void dragDropTab(DropEvent dropEvent) {
+ Component dropComp = dropEvent.getTarget();
+ Component draggComp = dropEvent.getDragged();
+
+ if (!isValidateDragDropComponent (dropComp, draggComp))
+ return;
+
+ Tabpanels tabpanels = this.getTabbox().getTabpanels();
+ int dropIndex = -1;
+ Component dropPanel = null;
+
+ if (dropComp instanceof Tab) {
+ dropIndex = this.getChildren().indexOf(dropComp);
+ dropPanel = tabpanels.getChildren().get(dropIndex);
+ }// other case is drop to tabs
+
+ int draggIndex = this.getChildren().indexOf(draggComp);
+ Component draggPanel = tabpanels.getChildren().get(draggIndex);
+
+ if (dropIndex == -1 || draggIndex > dropIndex) {//drop to end or to before drop tab
+ insertBefore(draggComp, dropComp);
+ tabpanels.insertBefore(draggPanel, dropPanel);
+ }else {
+ insertBefore(dropComp, draggComp);
+ tabpanels.insertBefore(dropPanel, draggPanel);
+ }
+
+ }
+
+ /**
+ * just allow drag|drop {@link Tab} on same {@link org.zkoss.zul.Tabs}
+ * @param dropComp
+ * @param draggComp
+ * @return
+ */
+ protected boolean isValidateDragDropComponent(Component dropComp, Component draggComp) {
+ if (dropComp == null || draggComp == null || !(dropComp instanceof org.zkoss.zul.Tab || dropComp instanceof org.zkoss.zul.Tabs) || !(draggComp instanceof Tab))// make sure drag and drop component is tab
+ return false;
+
+ if (dropComp instanceof org.zkoss.zul.Tabs && dropComp != this)// make sure drop on same tabs
+ return false;
+
+ if ((dropComp instanceof Tab && this != dropComp.getParent()) || this != draggComp.getParent())// make sure drag and drop on same tabbox
+ return false;
+
+ return true;
+ }
}
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 92625bcf22..a6090de566 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
@@ -73,6 +73,7 @@ public class WindowContainer extends AbstractUIPart
protected Component doCreatePart(Component parent)
{
tabbox = new Tabbox();
+ tabbox.setSupportTabDragDrop(true);
tabbox.setSclass("desktop-tabbox");
tabbox.setId("desktop_tabbox");
tabbox.setMaximalHeight(true);
diff --git a/org.adempiere.ui.zk/WEB-INF/zk.xml b/org.adempiere.ui.zk/WEB-INF/zk.xml
index 67b65afc6a..6501e80620 100644
--- a/org.adempiere.ui.zk/WEB-INF/zk.xml
+++ b/org.adempiere.ui.zk/WEB-INF/zk.xml
@@ -105,7 +105,11 @@
org.zkoss.zul.grid.rod
true
-
+
+ org.zkoss.zk.ui.EventListener.duplicateIgnored
+ true
+
+
org.zkoss.zk.ui.WebApp.name
iDempiere