/******************************************************************************
* Product: Posterita Ajax UI *
* Copyright (C) 2007 Posterita Ltd. All Rights Reserved. *
* This program is free software; you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License as published *
* by the Free Software Foundation. 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., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
* For the text or an alternative of this public license, you may reach us *
* Posterita Ltd., 3, Draper Avenue, Quatre Bornes, Mauritius *
* or via info@posterita.org or http://www.posterita.org/ *
*****************************************************************************/
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.zk.ui.util.Clients;
import org.zkoss.zul.Tab;
import org.zkoss.zul.Tabpanels;
/**
* Extend {@link org.zkoss.zul.Tabs}
* @author Ashley G Ramdass
* @date Mar 2, 2007
*/
public class Tabs extends org.zkoss.zul.Tabs implements EventListener
{
/**
* generated serial id
*/
private static final long serialVersionUID = 4939779587719677815L;
/**
* Default constructor
*/
public Tabs()
{
super();
}
/**
* override to set drag/drop for {@link Tab} already added to {@link Tabs} before {@link Tabs} added 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 enable drag and 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 disable drag and 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);
}// else is drop to tabs
int draggIndex = this.getChildren().indexOf(draggComp);
Component draggPanel = tabpanels.getChildren().get(draggIndex);
if (dropIndex != -1 && draggIndex < dropIndex) {
if (dropComp.getNextSibling() == null) {
dropIndex = -1;// drop to end
dropComp = null;
dropPanel = null;
}else {
dropIndex = dropIndex + 1;// insert before of tab next to drop tab
dropComp = dropComp.getNextSibling();
dropPanel = tabpanels.getChildren().get(dropIndex);
}
}
insertBefore(draggComp, dropComp);
tabpanels.insertBefore(draggPanel, dropPanel);
if (draggPanel.getPage() != null) {
StringBuilder script = new StringBuilder("zk.Widget.$('#").append(draggPanel.getUuid()).append("').rerender(0);");
Clients.evalJavaScript(script.toString());
}
}
/**
* Just allow drag|drop between {@link Tab} on same {@link org.zkoss.zul.Tabs}
* @param dropComp
* @param draggComp
* @return true if operation is valid, false otherwise
*/
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;
if ((dropComp instanceof org.adempiere.webui.component.Tab && ((org.adempiere.webui.component.Tab)dropComp).isDisableDraggDrop())
|| (draggComp instanceof org.adempiere.webui.component.Tab && ((org.adempiere.webui.component.Tab)draggComp).isDisableDraggDrop())
) {
return false;
}
return true;
}
}