IDEMPIERE-369 Master Detail layout improvements

This commit is contained in:
Heng Sin Low 2012-10-09 18:40:52 +08:00
parent 638d303322
commit d21fc00b60
40 changed files with 2494 additions and 1971 deletions

View File

@ -1006,11 +1006,6 @@ public class GridTab implements DataStatusListener, Evaluatee, Serializable
}
fireStateChangeEvent(new StateChangeEvent(this, StateChangeEvent.DATA_SAVE));
if (retValue) {
// refresh parent tabs
refreshParents();
}
return retValue;
}
catch (Exception e)
@ -1059,28 +1054,6 @@ public class GridTab implements DataStatusListener, Evaluatee, Serializable
return false;
}
private void refreshParents() {
if (isDetail()) {
// get parent tab
// the parent tab is the first tab above with level = this_tab_level-1
int level = m_vo.TabLevel;
for (int i = m_window.getTabIndex(this) - 1; i >= 0; i--) {
GridTab parentTab = m_window.getTab(i);
if (parentTab.m_vo.TabLevel == level-1) {
parentTab.dataRefresh(false);
// search for the next parent
if (parentTab.isDetail()) {
level = parentTab.m_vo.TabLevel;
} else {
break;
}
}
}
// refresh this tab
dataRefresh(false);
}
}
/**
* Do we need to Save?
* @param rowChange row change
@ -2514,7 +2487,7 @@ public class GridTab implements DataStatusListener, Evaluatee, Serializable
* @param fireEvents fire events
* @return current row
*/
private int setCurrentRow (int newCurrentRow, boolean fireEvents)
public int setCurrentRow (int newCurrentRow, boolean fireEvents)
{
int oldCurrentRow = m_currentRow;
m_currentRow = verifyRow (newCurrentRow);

View File

@ -42,7 +42,6 @@ import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
import org.adempiere.exceptions.DBException;
import org.adempiere.util.ContextRunnable;
import org.adempiere.util.ServerContext;
import org.compiere.Adempiere;
import org.compiere.util.CLogMgt;
@ -619,13 +618,8 @@ public class GridTable extends AbstractTableModel
m_sort = new ArrayList<MSort>(m_rowCount+10);
if (m_rowCount > 0)
{
if (m_rowCount < 1000)
m_loader.run();
else
{
m_loader.setContext(ServerContext.getCurrentInstance());
m_loaderFuture = Adempiere.getThreadPoolExecutor().submit(m_loader);
}
m_loader.setContext(ServerContext.getCurrentInstance());
m_loaderFuture = Adempiere.getThreadPoolExecutor().submit(m_loader);
}
else
m_loader.close();

View File

@ -103,4 +103,25 @@ public final class LayoutUtils {
window.doPopup();
Clients.response("_openPopupWindow_", new AuScript(window, script.toString()));
}
/**
* open popup window relative to the ref component
* @param ref
* @param window
* @param position
*/
public static void openOverlappedWindow(Component ref, Window window, String position) {
if (window.getPage() == null)
window.setPage(ref.getPage());
StringBuilder script = new StringBuilder();
script.append("_idempiere_popup_window('#")
.append(ref.getUuid())
.append("','#")
.append(window.getUuid())
.append("','")
.append(position)
.append("');");
window.doOverlapped();
Clients.response("_openPopupWindow_", new AuScript(window, script.toString()));
}
}

View File

@ -18,8 +18,8 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.logging.Level;
import org.adempiere.webui.adwindow.ADWindow;
import org.adempiere.webui.session.SessionManager;
import org.adempiere.webui.window.ADWindow;
import org.compiere.model.GridTab;
import org.compiere.model.MAsset;
import org.compiere.model.MBPartner;
@ -212,7 +212,7 @@ public class WRequest implements EventListener
// New - set Table/Record
if (e.getTarget() == m_new)
{
GridTab tab = frame.getADWindowPanel().getActiveGridTab();
GridTab tab = frame.getADWindowContent().getActiveGridTab();
tab.dataNew (false);
tab.setValue("AD_Table_ID", new Integer(m_AD_Table_ID));
tab.setValue("Record_ID", new Integer(m_Record_ID));

View File

@ -14,7 +14,7 @@
* ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA *
* or via info@compiere.org or http://www.compiere.org/license.html *
*****************************************************************************/
package org.adempiere.webui.panel;
package org.adempiere.webui.adwindow;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@ -100,7 +100,7 @@ public class ADSortTab extends Panel implements IADTabpanel
private boolean m_IdentifierTranslated = false;
private String m_ParentColumnName = null;
private AbstractADWindowPanel adWindowPanel = null;
private AbstractADWindowContent adWindowPanel = null;
// UI variables
private Label noLabel = new Label();
@ -136,6 +136,8 @@ public class ADSortTab extends Panel implements IADTabpanel
private GridTab gridTab;
private boolean uiCreated;
private boolean active = false;
private boolean isChanged;
/**
* Dynamic Init
@ -492,12 +494,17 @@ public class ADSortTab extends Panel implements IADTabpanel
* @param value
*/
private void setIsChanged(boolean value) {
isChanged = value;
if (adWindowPanel != null) {
adWindowPanel.getToolbar().enableSave(value);
adWindowPanel.getToolbar().enableIgnore(value);
}
}
public boolean isChanged() {
return isChanged;
}
/**
* @param event
*/
@ -612,7 +619,7 @@ public class ADSortTab extends Panel implements IADTabpanel
/* (non-Javadoc)
* @see org.compiere.grid.APanelTab#registerAPanel(APanel)
*/
public void registerAPanel (AbstractADWindowPanel panel)
public void registerAPanel (AbstractADWindowContent panel)
{
adWindowPanel = panel;
} // registerAPanel
@ -834,6 +841,7 @@ public class ADSortTab extends Panel implements IADTabpanel
}
public void activate(boolean b) {
active = b;
if (b && !uiCreated) createUI();
}
@ -902,5 +910,19 @@ public class ADSortTab extends Panel implements IADTabpanel
public boolean onEnterKey() {
return false;
}
@Override
public boolean isGridView() {
return false;
}
@Override
public boolean isActive() {
return active;
}
@Override
public void setDetailPaneMode(boolean detailMode, boolean vflex) {
}
} //ADSortTab

View File

@ -15,7 +15,7 @@
* or via info@posterita.org or http://www.posterita.org/ *
*****************************************************************************/
package org.adempiere.webui.panel;
package org.adempiere.webui.adwindow;
import java.util.ArrayList;
import java.util.HashMap;
@ -31,7 +31,6 @@ import org.adempiere.webui.component.Column;
import org.adempiere.webui.component.Columns;
import org.adempiere.webui.component.EditorBox;
import org.adempiere.webui.component.Grid;
import org.adempiere.webui.component.GridPanel;
import org.adempiere.webui.component.Group;
import org.adempiere.webui.component.Label;
import org.adempiere.webui.component.NumberBox;
@ -72,10 +71,10 @@ import org.zkoss.zul.Borderlayout;
import org.zkoss.zul.Center;
import org.zkoss.zul.DefaultTreeNode;
import org.zkoss.zul.Div;
import org.zkoss.zul.Groupfoot;
import org.zkoss.zul.Separator;
import org.zkoss.zul.Space;
import org.zkoss.zul.Treeitem;
import org.zkoss.zul.Vlayout;
import org.zkoss.zul.West;
import org.zkoss.zul.impl.XulElement;
@ -114,11 +113,11 @@ DataStatusListener, IADTabpanel
@SuppressWarnings("unused")
private GridWindow gridWindow;
private AbstractADWindowPanel windowPanel;
private AbstractADWindowContent windowPanel;
private int windowNo;
private Grid grid;
private Grid form;
private ArrayList<WEditor> editors = new ArrayList<WEditor>();
@ -126,7 +125,7 @@ DataStatusListener, IADTabpanel
private boolean uiCreated = false;
private GridPanel listPanel;
private GridView listPanel;
private Map<String, List<Row>> fieldGroupContents = new HashMap<String, List<Row>>();
@ -136,19 +135,18 @@ DataStatusListener, IADTabpanel
List<Group> allCollapsibleGroups = new ArrayList<Group>();
private Component formComponent = null;
private Component formContainer = null;
private ADTreePanel treePanel = null;
private GridTabDataBinder dataBinder;
private Map<Integer, Group> includedTab = new HashMap<Integer, Group>();
private Map<Integer, Groupfoot> includedTabFooter = new HashMap<Integer, Groupfoot>();
private boolean active = false;
private Group currentGroup;
private Component detailPane;
public ADTabpanel()
{
init();
@ -164,16 +162,47 @@ DataStatusListener, IADTabpanel
{
LayoutUtils.addSclass("adtab-content", this);
grid = new Grid();
//have problem moving the following out as css class
grid.setHflex("1");
grid.setHeight("100%");
grid.setVflex(true);
grid.setSclass("grid-layout");
this.setWidth("100%");
form = new Grid();
form.setHflex("1");
form.setHeight(null);
form.setVflex(false);
form.setSclass("grid-layout");
form.addEventListener(Events.ON_FOCUS, this);
listPanel = new GridPanel();
listPanel = new GridView();
listPanel.getListbox().addEventListener(Events.ON_DOUBLE_CLICK, this);
}
public void addDetails(Component component) {
if (formContainer.isVisible()) {
detailPane = component;
if (formContainer instanceof Borderlayout) {
form.getParent().appendChild(detailPane);
} else {
formContainer.appendChild(component);
}
} else {
listPanel.addDetails(component);
}
}
public Component removeDetails() {
Component details = null;
if (listPanel.isVisible()) {
details = listPanel.removeDetails();
} else {
if (detailPane != null) {
if (detailPane.getParent() != null) {
details = detailPane;
detailPane.detach();
}
detailPane = null;
}
}
return details;
}
/**
*
@ -182,7 +211,7 @@ DataStatusListener, IADTabpanel
* @param gridTab
* @param gridWindow
*/
public void init(AbstractADWindowPanel winPanel, int windowNo, GridTab gridTab,
public void init(AbstractADWindowContent winPanel, int windowNo, GridTab gridTab,
GridWindow gridWindow)
{
this.windowNo = windowNo;
@ -214,12 +243,15 @@ DataStatusListener, IADTabpanel
layout.appendChild(west);
Center center = new Center();
center.setFlex(true);
center.appendChild(grid);
center.setSclass("adtab-form");
Vlayout div = new Vlayout();
div.appendChild(form);
center.appendChild(div);
div.setVflex("1");
div.setHflex("1");
div.setSclass("adtab-form");
layout.appendChild(center);
formComponent = layout;
formContainer = layout;
treePanel.getTree().addEventListener(Events.ON_SELECT, this);
if (AEnv.isTablet())
@ -230,16 +262,18 @@ DataStatusListener, IADTabpanel
}
else
{
Div div = new Div();
Vlayout div = new Vlayout();
div.setSclass("adtab-form");
div.appendChild(grid);
div.appendChild(form);
div.setVflex("1");
div.setWidth("100%");
this.appendChild(div);
formComponent = div;
formContainer = div;
if (AEnv.isTablet())
{
LayoutUtils.addSclass("tablet-scrolling", div);
}
}
}
this.appendChild(listPanel);
listPanel.setVisible(false);
@ -264,7 +298,7 @@ DataStatusListener, IADTabpanel
// set size in percentage per column leaving a MARGIN on right
Columns columns = new Columns();
grid.appendChild(columns);
form.appendChild(columns);
String numColsS=String.valueOf(numCols);
int equalWidth = 98 / numCols;
@ -274,7 +308,7 @@ DataStatusListener, IADTabpanel
columns.appendChild(col);
}
Rows rows = grid.newRows();
Rows rows = form.newRows();
GridField fields[] = gridTab.getFields();
Row row = new Row();
int actualxpos = 0;
@ -286,55 +320,6 @@ DataStatusListener, IADTabpanel
if (!field.isDisplayed())
continue;
//included tab
if (field.getIncluded_Tab_ID() > 0)
{
// NOT CHANGING INCLUDED TAB AS THIS IS BEING REDESIGNED WITH
// IDEMPIERE-369 Master Detail layout improvements
if (row.getChildren().size() == 2)
{
row.appendChild(createSpacer());
row.appendChild(createSpacer());
row.appendChild(createSpacer());
rows.appendChild(row);
if (rowList != null)
rowList.add(row);
} else if (row.getChildren().size() > 0)
{
rows.appendChild(row);
if (rowList != null)
rowList.add(row);
}
//end current field group
if (currentGroup != null) {
Groupfoot rowg = new Groupfoot();
rows.appendChild(rowg);
currentGroup = null;
currentFieldGroup = null;
}
row = new Row();
row.setSpans("5");
row.appendChild(new Separator());
rows.appendChild(row);
Group rowg = new Group();
rowg.setSpans("2,3");
rows.appendChild(rowg);
includedTab.put(field.getIncluded_Tab_ID(), (Group)rowg);
Groupfoot rowgf = new Groupfoot();
rows.appendChild(rowgf);
includedTabFooter.put(field.getIncluded_Tab_ID(), (Groupfoot)rowgf);
row = new Row();
row.setSpans("5");
row.appendChild(new Separator());
rows.appendChild(row);
row = new Row();
continue;
}
// field group
String fieldGroup = field.getFieldGroup();
if (!Util.isEmpty(fieldGroup) && !fieldGroup.equals(currentFieldGroup)) // group changed
@ -569,7 +554,7 @@ DataStatusListener, IADTabpanel
} // all components
//hide row if all editor within the row is invisible
List<Component> rows = grid.getRows().getChildren();
List<Component> rows = form.getRows().getChildren();
for (Component comp : rows)
{
if (comp instanceof Row) {
@ -743,7 +728,7 @@ DataStatusListener, IADTabpanel
listPanel.deactivate();
} else {
if (activate) {
formComponent.setVisible(activate);
formContainer.setVisible(activate);
setFocusToField();
}
}
@ -751,6 +736,9 @@ DataStatusListener, IADTabpanel
if (gridTab.getRecord_ID() > 0 && gridTab.isTreeTab() && treePanel != null) {
setSelectedNode(gridTab.getRecord_ID());
}
Event event = new Event("onActivate", this, activate);
Events.sendEvent(event);
}
/**
@ -790,11 +778,7 @@ DataStatusListener, IADTabpanel
{
if (event.getTarget() == listPanel.getListbox())
{
if (windowPanel != null) {
windowPanel.onToggle();
} else {
this.switchRowPresentation();
}
Events.sendEvent(this, new Event("onToggle", this));
}
else if (event.getTarget() == treePanel.getTree()) {
Treeitem item = treePanel.getTree().getSelectedItem();
@ -804,6 +788,8 @@ DataStatusListener, IADTabpanel
if (gridTab.getRecord_ID() > 0 && gridTab.isTreeTab() && treePanel != null) {
setSelectedNode(gridTab.getRecord_ID());
}
} else {
System.out.println(event.getName() + " " + event.getTarget());
}
}
@ -979,19 +965,25 @@ DataStatusListener, IADTabpanel
* Toggle between form and grid view
*/
public void switchRowPresentation() {
if (formComponent.isVisible()) {
formComponent.setVisible(false);
Component details = removeDetails();
if (formContainer.isVisible()) {
formContainer.setVisible(false);
} else {
formComponent.setVisible(true);
formComponent.getParent().invalidate();
formContainer.setVisible(true);
formContainer.getParent().invalidate();
}
listPanel.setVisible(!formComponent.isVisible());
listPanel.setVisible(!formContainer.isVisible());
if (listPanel.isVisible()) {
listPanel.refresh(gridTab);
listPanel.scrollToCurrentRow();
} else {
listPanel.deactivate();
}
if (details != null)
addDetails(details);
Events.sendEvent(this, new Event("onSwitchView", this));
}
class ZoomListener implements EventListener {
@ -1019,14 +1011,14 @@ DataStatusListener, IADTabpanel
@Override
public void focus() {
if (formComponent.isVisible())
if (formContainer.isVisible())
this.setFocusToField();
else
listPanel.focus();
}
public void setFocusToField(String columnName) {
if (formComponent.isVisible()) {
if (formContainer.isVisible()) {
boolean found = false;
for (WEditor editor : editors) {
if (found)
@ -1063,8 +1055,23 @@ DataStatusListener, IADTabpanel
*
* @return GridPanel
*/
public GridPanel getGridView() {
public GridView getGridView() {
return listPanel;
}
public boolean isActive() {
return active;
}
@Override
public void setDetailPaneMode(boolean detailPaneMode, boolean vflex) {
if (detailPaneMode) {
detailPane = null;
this.setVflex("true");
} else {
this.setVflex(Boolean.toString(vflex));
}
listPanel.setDetailPaneMode(detailPaneMode, vflex);
}
}

View File

@ -11,11 +11,12 @@
* with this program; if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
*****************************************************************************/
package org.adempiere.webui.panel;
package org.adempiere.webui.adwindow;
import org.adempiere.webui.component.SimpleTreeModel;
import org.adempiere.webui.component.ToolBarButton;
import org.adempiere.webui.panel.TreeSearchPanel;
import org.adempiere.webui.util.TreeUtils;
import org.compiere.util.Env;
import org.compiere.util.Msg;

View File

@ -15,12 +15,11 @@
* or via info@posterita.org or http://www.posterita.org/ *
*****************************************************************************/
package org.adempiere.webui.window;
package org.adempiere.webui.adwindow;
import java.util.Properties;
import org.adempiere.webui.desktop.IDesktop;
import org.adempiere.webui.panel.ADWindowPanel;
import org.adempiere.webui.part.AbstractUIPart;
import org.adempiere.webui.session.SessionManager;
import org.compiere.model.MQuery;
@ -34,7 +33,7 @@ import org.zkoss.zk.ui.Component;
*/
public class ADWindow extends AbstractUIPart
{
private ADWindowPanel windowPanel;
private ADWindowContent windowContent;
private Properties ctx;
private int adWindowId;
private String _title;
@ -63,7 +62,7 @@ public class ADWindow extends AbstractUIPart
private void init()
{
windowPanel = new ADWindowPanel(ctx, windowNo);
windowContent = new ADWindowContent(ctx, windowNo);
}
public String getTitle()
@ -73,12 +72,12 @@ public class ADWindow extends AbstractUIPart
protected Component doCreatePart(Component parent)
{
windowPanelComponent = windowPanel.createPart(parent);
windowPanelComponent = windowContent.createPart(parent);
windowPanelComponent.setAttribute("ADWindow", this);
windowPanelComponent.setAttribute(IDesktop.WINDOWNO_ATTRIBUTE, windowNo);
if (windowPanel.initPanel(adWindowId, query))
if (windowContent.initPanel(adWindowId, query))
{
_title = windowPanel.getTitle();
_title = windowContent.getTitle();
return windowPanelComponent;
}
else
@ -93,9 +92,9 @@ public class ADWindow extends AbstractUIPart
}
/**
* @return ADWindowPanel
* @return ADWindowContent
*/
public ADWindowPanel getADWindowPanel() {
return windowPanel;
public ADWindowContent getADWindowContent() {
return windowContent;
}
}

View File

@ -21,17 +21,16 @@
* - Idalica Corporation *
*****************************************************************************/
package org.adempiere.webui.panel;
package org.adempiere.webui.adwindow;
import java.util.List;
import java.util.Properties;
import org.adempiere.webui.LayoutUtils;
import org.adempiere.webui.component.CompositeADTab;
import org.adempiere.webui.component.IADTab;
import org.adempiere.webui.component.Tabbox;
import org.adempiere.webui.component.Tabpanel;
import org.adempiere.webui.component.Tabs;
import org.adempiere.webui.panel.ITabOnCloseHandler;
import org.adempiere.webui.part.ITabOnSelectHandler;
import org.adempiere.webui.session.SessionManager;
import org.adempiere.webui.util.UserPreference;
@ -48,6 +47,7 @@ import org.zkoss.zk.ui.event.Events;
import org.zkoss.zk.ui.event.KeyEvent;
import org.zkoss.zul.Borderlayout;
import org.zkoss.zul.Center;
import org.zkoss.zul.Div;
import org.zkoss.zul.East;
import org.zkoss.zul.North;
import org.zkoss.zul.South;
@ -64,10 +64,10 @@ import org.zkoss.zul.West;
* @date Feb 25, 2007
* @version $Revision: 0.10 $
*/
public class ADWindowPanel extends AbstractADWindowPanel
public class ADWindowContent extends AbstractADWindowContent
{
@SuppressWarnings("unused")
private static final CLogger logger = CLogger.getCLogger(ADWindowPanel.class);
private static final CLogger logger = CLogger.getCLogger(ADWindowContent.class);
private Borderlayout layout;
@ -77,15 +77,14 @@ public class ADWindowPanel extends AbstractADWindowPanel
private East east;
private Keylistener keyListener;
private Keylistener keyListener;
public ADWindowPanel(Properties ctx, int windowNo)
public ADWindowContent(Properties ctx, int windowNo)
{
super(ctx, windowNo);
}
protected Component doCreatePart(Component parent)
protected Component doCreatePart(Component parent)
{
layout = new Borderlayout();
if (parent != null) {
@ -100,8 +99,16 @@ public class ADWindowPanel extends AbstractADWindowPanel
n.setParent(layout);
n.setCollapsible(false);
n.setSclass("adwindow-north");
toolbar.setParent(n);
Div div = new Div();
div.setHflex("1");
div.setVflex("1");
n.appendChild(div);
toolbar.setParent(div);
toolbar.setWindowNo(getWindowNo());
breadCrumb = new BreadCrumb(getWindowNo());
breadCrumb.setStyle("background-color: #e9e9e9");
breadCrumb.setToolbarListener(this);
div.appendChild(breadCrumb);
//status bar
South s = new South();
@ -112,50 +119,9 @@ public class ADWindowPanel extends AbstractADWindowPanel
LayoutUtils.addSclass("adwindow-status", statusBar);
if (adTab.isUseExternalSelection())
{
String tabPlacement = SessionManager.getSessionApplication().getUserPreference().getProperty(UserPreference.P_WINDOW_TAB_PLACEMENT);
if (tabPlacement == null || "left".equalsIgnoreCase(tabPlacement))
{
west = new West();
layout.appendChild(west);
west.setSplittable(false);
west.setAutoscroll(true);
west.setFlex(true);
LayoutUtils.addSclass("adwindow-nav adwindow-left-nav", west);
adTab.setTabplacement(IADTab.LEFT);
adTab.getTabSelectionComponent().setParent(west);
if (SessionManager.getSessionApplication().getUserPreference().isPropertyBool(UserPreference.P_WINDOW_TAB_COLLAPSIBLE))
{
west.setTitle(Msg.getElement(Env.getCtx(), "AD_Tab_ID"));
west.setCollapsible(true);
}
}
else
{
east = new East();
layout.appendChild(east);
east.setSplittable(false);
east.setAutoscroll(true);
east.setFlex(true);
LayoutUtils.addSclass("adwindow-nav adwindow-right-nav", east);
adTab.setTabplacement(IADTab.RIGHT);
adTab.getTabSelectionComponent().setParent(east);
if (SessionManager.getSessionApplication().getUserPreference().isPropertyBool(UserPreference.P_WINDOW_TAB_COLLAPSIBLE))
{
east.setTitle(Msg.getElement(Env.getCtx(), "AD_Tab_ID"));
east.setCollapsible(true);
}
}
LayoutUtils.addSclass("adwindow-nav-content", (HtmlBasedComponent) adTab.getTabSelectionComponent());
}
contentArea = new Center();
contentArea.setParent(layout);
contentArea.setAutoscroll(true);
contentArea.setFlex(true);
adTab.createPart(contentArea);
if (parent instanceof Tabpanel) {
@ -174,7 +140,7 @@ public class ADWindowPanel extends AbstractADWindowPanel
layout.setAttribute(ITabOnSelectHandler.ATTRIBUTE_KEY, new ITabOnSelectHandler() {
public void onSelect() {
IADTab adTab = getADTab();
IADTabbox adTab = getADTab();
if (adTab != null) {
IADTabpanel iadTabpanel = adTab.getSelectedTabpanel();
if (iadTabpanel != null && iadTabpanel instanceof ADTabpanel) {
@ -191,9 +157,9 @@ public class ADWindowPanel extends AbstractADWindowPanel
return layout;
}
protected IADTab createADTab()
protected IADTabbox createADTab()
{
CompositeADTab composite = new CompositeADTab();
CompositeADTabbox composite = new CompositeADTabbox();
return composite;
}
@ -240,7 +206,7 @@ public class ADWindowPanel extends AbstractADWindowPanel
class TabOnCloseHanlder implements ITabOnCloseHandler {
public void onClose(Tabpanel tabPanel) {
if (ADWindowPanel.this.onExit()) {
if (ADWindowContent.this.onExit()) {
Tab tab = tabPanel.getLinkedTab();
Tabbox tabbox = (Tabbox) tab.getTabbox();
if (tabbox.getSelectedTab() == tab) {

View File

@ -15,7 +15,7 @@
* or via info@posterita.org or http://www.posterita.org/ *
*****************************************************************************/
package org.adempiere.webui.component;
package org.adempiere.webui.adwindow;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@ -28,6 +28,8 @@ import java.util.logging.Level;
import org.adempiere.webui.AdempiereIdGenerator;
import org.adempiere.webui.LayoutUtils;
import org.adempiere.webui.component.FToolbar;
import org.adempiere.webui.component.ToolBarButton;
import org.adempiere.webui.event.ToolbarListener;
import org.adempiere.webui.session.SessionManager;
import org.compiere.model.MRole;
@ -52,7 +54,7 @@ import org.zkoss.zul.Space;
* @author Cristina Ghita, www.arhipac.ro
* <li>FR [ 2076330 ] Add new methods in CWindowToolbar class
*/
public class CWindowToolbar extends FToolbar implements EventListener<Event>
public class ADWindowToolbar extends FToolbar implements EventListener<Event>
{
/**
*
@ -61,7 +63,7 @@ public class CWindowToolbar extends FToolbar implements EventListener<Event>
private static final String BTNPREFIX = "Btn";
private static CLogger log = CLogger.getCLogger(CWindowToolbar.class);
private static CLogger log = CLogger.getCLogger(ADWindowToolbar.class);
private ToolBarButton btnIgnore;
@ -75,8 +77,6 @@ public class CWindowToolbar extends FToolbar implements EventListener<Event>
private ToolBarButton btnParentRecord, btnDetailRecord;
private ToolBarButton btnFirst, btnPrevious, btnNext, btnLast;
private ToolBarButton btnReport, btnArchive, btnPrint;
private ToolBarButton btnZoomAcross, btnActiveWorkflows, btnRequests, btnProductInfo;
@ -114,12 +114,12 @@ public class CWindowToolbar extends FToolbar implements EventListener<Event>
// public int lastModifiers;
//
public CWindowToolbar()
public ADWindowToolbar()
{
this(0);
}
public CWindowToolbar(int windowNo) {
public ADWindowToolbar(int windowNo) {
setWindowNo(windowNo);
init();
}
@ -145,11 +145,7 @@ public class CWindowToolbar extends FToolbar implements EventListener<Event>
btnGridToggle = createButton("Toggle", "Multi", "Multi");
addSeparator();
btnParentRecord = createButton("ParentRecord", "Parent", "Parent");
btnDetailRecord = createButton("DetailRecord", "Detail", "Detail");
btnFirst = createButton("First", "First", "First");
btnPrevious = createButton("Previous", "Previous", "Previous");
btnNext = createButton("Next", "Next", "Next");
btnLast = createButton("Last", "Last", "Last");
btnDetailRecord = createButton("DetailRecord", "Detail", "Detail");
addSeparator();
btnReport = createButton("Report", "Report", "Report");
btnArchive = createButton("Archive", "Archive", "Archive");
@ -259,11 +255,7 @@ public class CWindowToolbar extends FToolbar implements EventListener<Event>
keyMap.put(KeyEvent.F12, btnPrint);
altKeyMap.put(KeyEvent.LEFT, btnParentRecord);
altKeyMap.put(KeyEvent.RIGHT, btnDetailRecord);
altKeyMap.put(KeyEvent.UP, btnPrevious);
altKeyMap.put(KeyEvent.DOWN, btnNext);
altKeyMap.put(KeyEvent.PAGE_UP, btnFirst);
altKeyMap.put(KeyEvent.PAGE_DOWN, btnLast);
altKeyMap.put(KeyEvent.RIGHT, btnDetailRecord);
altKeyMap.put(VK_P, btnReport);
altKeyMap.put(VK_Z, btnIgnore);
@ -363,15 +355,7 @@ public class CWindowToolbar extends FToolbar implements EventListener<Event>
}
this.event = null;
}
public void enableNavigation(boolean enabled)
{
this.btnFirst.setDisabled(!enabled);
this.btnPrevious.setDisabled(!enabled);
this.btnNext.setDisabled(!enabled);
this.btnLast.setDisabled(!enabled);
}
public void enableTabNavigation(boolean enabled)
{
enableTabNavigation(enabled, enabled);
@ -383,18 +367,6 @@ public class CWindowToolbar extends FToolbar implements EventListener<Event>
this.btnDetailRecord.setDisabled(!enableDetail);
}
public void enableFirstNavigation(boolean enabled)
{
this.btnFirst.setDisabled(!enabled);
this.btnPrevious.setDisabled(!enabled);
}
public void enableLastNavigation(boolean enabled)
{
this.btnLast.setDisabled(!enabled);
this.btnNext.setDisabled(!enabled);
}
public void enableRefresh(boolean enabled)
{
this.btnRefresh.setDisabled(!enabled);

View File

@ -15,16 +15,13 @@
* or via info@posterita.org or http://www.posterita.org/ *
*****************************************************************************/
package org.adempiere.webui.component;
package org.adempiere.webui.adwindow;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.adempiere.webui.panel.ADTabpanel;
import org.adempiere.webui.panel.AbstractADWindowPanel;
import org.adempiere.webui.panel.CustomizeGridViewPanel;
import org.adempiere.webui.panel.IADTabpanel;
import org.adempiere.webui.part.AbstractUIPart;
import org.compiere.model.DataStatusEvent;
import org.compiere.model.GridField;
@ -40,18 +37,18 @@ import org.compiere.util.Evaluator;
* @date Feb 25, 2007
* @version $Revision: 0.10 $
*/
public abstract class AbstractADTab extends AbstractUIPart implements IADTab
public abstract class AbstractADTabbox extends AbstractUIPart implements IADTabbox
{
/** Logger */
private static CLogger log = CLogger.getCLogger (AbstractADTab.class);
private static CLogger log = CLogger.getCLogger (AbstractADTabbox.class);
/** List of dependent Variables */
private ArrayList<String> m_dependents = new ArrayList<String>();
/** Tabs associated to this tab box */
protected List<IADTabpanel> tabPanelList = new ArrayList<IADTabpanel>();
protected AbstractADWindowPanel adWindowPanel;
protected AbstractADWindowContent adWindowPanel;
public AbstractADTab()
public AbstractADTabbox()
{
}
@ -327,7 +324,7 @@ public abstract class AbstractADTab extends AbstractUIPart implements IADTab
updateSelectedIndex(oldIndex, newIndex);
}
public void setADWindowPanel(AbstractADWindowPanel abstractADWindowPanel) {
public void setADWindowPanel(AbstractADWindowContent abstractADWindowPanel) {
this.adWindowPanel = abstractADWindowPanel;
}
}

View File

@ -0,0 +1,434 @@
/******************************************************************************
* Copyright (C) 2012 Heng Sin Low *
* Copyright (C) 2012 Trek Global *
* 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. *
*****************************************************************************/
package org.adempiere.webui.adwindow;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import org.adempiere.webui.AdempiereIdGenerator;
import org.adempiere.webui.LayoutUtils;
import org.adempiere.webui.component.Label;
import org.adempiere.webui.component.Menupopup;
import org.adempiere.webui.component.ToolBar;
import org.adempiere.webui.component.ToolBarButton;
import org.adempiere.webui.component.Window;
import org.adempiere.webui.event.ToolbarListener;
import org.adempiere.webui.session.SessionManager;
import org.adempiere.webui.window.WRecordInfo;
import org.compiere.model.DataStatusEvent;
import org.compiere.model.MRole;
import org.compiere.util.Env;
import org.compiere.util.Msg;
import org.zkoss.zhtml.Text;
import org.zkoss.zk.ui.Execution;
import org.zkoss.zk.ui.Executions;
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.KeyEvent;
import org.zkoss.zk.ui.event.MouseEvent;
import org.zkoss.zk.ui.util.Clients;
import org.zkoss.zul.Caption;
import org.zkoss.zul.Div;
import org.zkoss.zul.Hbox;
import org.zkoss.zul.Hlayout;
import org.zkoss.zul.Image;
import org.zkoss.zul.Menuitem;
import org.zkoss.zul.Space;
/**
* @author hengsin
*
*/
public class BreadCrumb extends Div implements EventListener<Event>{
private static final String INFO_INDICATOR_IMAGE = "/images/InfoIndicator16.png";
private static final String ERROR_INDICATOR_IMAGE = "/images/ErrorIndicator16.png";
/**
* generated serial id
*/
private static final long serialVersionUID = 929253935475618911L;
private static final String BTNPREFIX = "Btn";
private Hbox layout;
private ToolBarButton btnFirst, btnPrevious, btnNext, btnLast, btnRecordInfo;
private LinkedHashMap<String, String> links;
private int windowNo;
private HashMap<String, ToolBarButton> buttons = new HashMap<String, ToolBarButton>();
private Map<Integer, ToolBarButton> altKeyMap = new HashMap<Integer, ToolBarButton>();
private DataStatusEvent m_dse;
private String m_text;
private boolean m_statusError;
private String m_statusText;
private Window msgPopup;
private Div msgPopupCnt;
private ToolbarListener toolbarListener;
private Hlayout toolbarContainer;
private Hbox messageContainer;
private Caption msgPopupCaption;
/**
*
*/
public BreadCrumb(int windowNo) {
this.windowNo = windowNo;
layout = new Hbox();
layout.setPack("start");
layout.setAlign("center");
this.appendChild(layout);
layout.setHeight("100%");
layout.setStyle("float: left");
this.setVisible(false);
this.setSclass("adwindow-breadcrumb");
toolbarContainer = new Hlayout();
layout.appendChild(toolbarContainer);
ToolBar toolbar = new ToolBar();
toolbarContainer.appendChild(toolbar);
btnFirst = createButton("First", "First", "First");
toolbar.appendChild(btnFirst);
btnPrevious = createButton("Previous", "Previous", "Previous");
toolbar.appendChild(btnPrevious);
btnRecordInfo = new ToolBarButton();
btnRecordInfo.setLabel("");
btnRecordInfo.setStyle("font-size: 12px");
btnRecordInfo.setTooltiptext("Record Info");
btnRecordInfo.addEventListener(Events.ON_CLICK, this);
toolbar.appendChild(btnRecordInfo);
btnNext = createButton("Next", "Next", "Next");
toolbar.appendChild(btnNext);
btnLast = createButton("Last", "Last", "Last");
toolbar.appendChild(btnLast);
messageContainer = new Hbox();
messageContainer.setStyle("float: right; height: 30px;");
messageContainer.setAlign("center");
appendChild(messageContainer);
altKeyMap.put(KeyEvent.UP, btnPrevious);
altKeyMap.put(KeyEvent.DOWN, btnNext);
altKeyMap.put(KeyEvent.PAGE_UP, btnFirst);
altKeyMap.put(KeyEvent.PAGE_DOWN, btnLast);
createPopup();
toolbar.setStyle("background-image: none; background-color: transparent; border: none;");
}
public void setToolbarListener(ToolbarListener listener) {
this.toolbarListener = listener;
}
public void addPath(String label, String id, boolean clickable) {
if (clickable) {
BreadCrumbLink a = new BreadCrumbLink();
a.setLabel(label);
a.setPathId(id);
a.addEventListener(Events.ON_CLICK, this);
if (layout.getChildren().size() > 1) {
Label symbol = new Label();
symbol.setValue(" > ");
layout.insertBefore(symbol, toolbarContainer);
}
layout.insertBefore(a, toolbarContainer);
} else {
Label pathLabel = new Label();
pathLabel.setValue(label);
if (layout.getChildren().size() > 1) {
Label symbol = new Label();
symbol.setValue(" > ");
layout.insertBefore(symbol, toolbarContainer);
}
pathLabel.setStyle("font-weight: bold");
layout.insertBefore(pathLabel, toolbarContainer);
}
}
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.addEventListener(Events.ON_CLICK, new EventListener<Event>() {
@Override
public void onEvent(Event event) throws Exception {
Menupopup popup = new Menupopup();
for(Map.Entry<String, String>entry : BreadCrumb.this.links.entrySet()) {
final Menuitem item = new Menuitem();
item.setLabel(entry.getValue());
item.setValue(entry.getKey());
item.addEventListener(Events.ON_CLICK, BreadCrumb.this);
popup.appendChild(item);
}
popup.setPage(pathLabel.getPage());
popup.open(pathLabel);
}
});
}
@Override
public void onEvent(Event event) throws Exception {
if (event.getTarget() == btnRecordInfo) {
if (m_dse == null
|| m_dse.CreatedBy == null
|| !MRole.getDefault().isShowPreference())
return;
String title = Msg.getMsg(Env.getCtx(), "Who") + m_text;
new WRecordInfo (title, m_dse);
} else if (event.getTarget().getParent() == messageContainer) {
showPopup();
} else if (event.getTarget() == btnFirst) {
if (toolbarListener != null)
toolbarListener.onFirst();
} else if (event.getTarget() == btnPrevious) {
if (toolbarListener != null)
toolbarListener.onPrevious();
} else if (event.getTarget() == btnNext) {
if (toolbarListener != null)
toolbarListener.onNext();
} else if (event.getTarget() == btnLast) {
if (toolbarListener != null)
toolbarListener.onLast();
} else {
MouseEvent me = (MouseEvent) event;
Events.sendEvent(this, me);
}
}
public void reset() {
layout.getChildren().clear();
layout.appendChild(toolbarContainer);
this.links = null;
}
private void enableFirstNavigation(boolean enabled)
{
this.btnFirst.setDisabled(!enabled);
this.btnPrevious.setDisabled(!enabled);
}
private void enableLastNavigation(boolean enabled)
{
this.btnLast.setDisabled(!enabled);
this.btnNext.setDisabled(!enabled);
}
public void enableNavigation(boolean enabled)
{
this.btnFirst.setDisabled(!enabled);
this.btnPrevious.setDisabled(!enabled);
this.btnNext.setDisabled(!enabled);
this.btnLast.setDisabled(!enabled);
}
private ToolBarButton createButton(String name, String image, String tooltip)
{
ToolBarButton btn = new ToolBarButton("");
btn.setName(BTNPREFIX+name);
if (windowNo > 0)
btn.setAttribute(AdempiereIdGenerator.ZK_COMPONENT_PREFIX_ATTRIBUTE, "unq" + btn.getName() + "_" + windowNo);
else
btn.setAttribute(AdempiereIdGenerator.ZK_COMPONENT_PREFIX_ATTRIBUTE, btn.getName());
btn.setImage("/images/"+image + "24.png");
btn.setTooltiptext(Msg.getMsg(Env.getCtx(),tooltip));
btn.setSclass("toolbar-button");
buttons.put(name, btn);
this.appendChild(btn);
//make toolbar button last to receive focus
btn.setTabindex(0);
btn.addEventListener(Events.ON_CLICK, this);
btn.setDisabled(true);
return btn;
}
/**
* @param text
*/
public void setStatusDB (String text)
{
setStatusDB(text, null);
}
/**
* @param text
* @param dse
*/
public void setStatusDB (String text, DataStatusEvent dse)
{
if (text == null || text.length() == 0)
{
btnRecordInfo.setLabel("");
}
else
{
btnRecordInfo.setLabel(text);
}
m_text = text;
m_dse = dse;
if (m_dse != null) {
enableFirstNavigation(m_dse.getCurrentRow() > 0);
enableLastNavigation(m_dse.getTotalRows() > m_dse.getCurrentRow()+1);
}
}
/**
* @param text
*/
public void setStatusLine (String text)
{
setStatusLine(text, false);
}
/**
* @param text
* @param error
*/
public void setStatusLine (String text, boolean error)
{
Execution execution = Executions.getCurrent();
if (execution != null) {
String key = this.getClass().getName()+"."+getUuid();
Object o = execution.getAttribute(key);
if (o != null) {
if (text == null || text.trim().length() == 0)
return;
} else {
execution.setAttribute(key, Boolean.TRUE);
}
}
m_statusText = text;
m_statusError = error;
messageContainer.getChildren().clear();
if (text == null || text.trim().length() == 0 )
return;
Image image = null;
if (error)
image = new Image(ERROR_INDICATOR_IMAGE);
else
image = new Image(INFO_INDICATOR_IMAGE);
image.setAttribute("org.zkoss.zul.image.preload", Boolean.TRUE);
messageContainer.appendChild(image);
String labelText = buildLabelText(m_statusText);
if (error) {
Clients.showNotification(labelText, "error", image, "overlap_start", 3500, true);
}
Label label = new Label(labelText);
messageContainer.appendChild(label);
if (labelText.length() != m_statusText.length()) {
image.addEventListener(Events.ON_CLICK, this);
image.setStyle("cursor: pointer");
label.addEventListener(Events.ON_CLICK, this);
label.setStyle("cursor: pointer");
label = new Label(" ...");
label.setStyle("cursor: pointer");
messageContainer.appendChild(label);
label.addEventListener(Events.ON_CLICK, this);
}
messageContainer.appendChild(new Space());
createPopupContent();
}
private String buildLabelText(String statusText) {
if (statusText == null)
return "";
if (statusText.length() <= 80)
return statusText;
int index = statusText.indexOf(" - java.lang.Exception");
if (index > 0)
return statusText.substring(0, index);
return statusText.substring(0, 80);
}
protected void createPopupContent() {
Text t = new Text(m_statusText);
msgPopupCnt.getChildren().clear();
msgPopupCnt.appendChild(t);
}
/**
*
* @return current status line text
*/
public String getStatusLine() {
return m_statusText;
}
private void createPopup() {
msgPopupCnt = new Div();
msgPopupCnt.setVflex("1");
msgPopup = new Window();
msgPopup.setBorder(true);
msgPopup.setClosable(true);
msgPopup.setSizable(true);
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);
}
private void showPopup() {
msgPopupCaption.setImage(m_statusError ? ERROR_INDICATOR_IMAGE : INFO_INDICATOR_IMAGE);
LayoutUtils.openOverlappedWindow(messageContainer, msgPopup, "overlap_end");
}
@Override
public void onPageDetached(Page page) {
super.onPageDetached(page);
if (msgPopup != null)
msgPopup.detach();
}
public void setNavigationToolbarVisibility(boolean visible) {
toolbarContainer.setVisible(visible);
}
}

View File

@ -0,0 +1,39 @@
/******************************************************************************
* Copyright (C) 2012 Heng Sin Low *
* Copyright (C) 2012 Trek Global *
* 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. *
*****************************************************************************/
package org.adempiere.webui.adwindow;
import org.zkoss.zul.A;
/**
* @author hengsin
*
*/
public class BreadCrumbLink extends A {
/**
* generated serial id
*/
private static final long serialVersionUID = 170361731431877695L;
private String pathId;
public String getPathId() {
return pathId;
}
public void setPathId(String pathId) {
this.pathId = pathId;
}
}

View File

@ -0,0 +1,646 @@
/******************************************************************************
* 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.adwindow;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import org.adempiere.util.Callback;
import org.adempiere.webui.component.ADTabListModel;
import org.adempiere.webui.component.ADTabListModel.ADTabLabel;
import org.adempiere.webui.window.FDialog;
import org.compiere.model.DataStatusEvent;
import org.compiere.model.DataStatusListener;
import org.compiere.model.GridField;
import org.compiere.model.GridTab;
import org.compiere.util.CLogger;
import org.compiere.util.Env;
import org.compiere.util.Msg;
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.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.Menuitem;
import org.zkoss.zul.Vlayout;
/**
*
* @author <a href="mailto:agramdass@gmail.com">Ashley G Ramdass</a>
* @author <a href="mailto:hengsin@gmail.com">Low Heng Sin</a>
* @date Feb 25, 2007
* @version $Revision: 0.10 $
*/
public class CompositeADTabbox extends AbstractADTabbox
{
private static final String ON_TOGGLE_EVENT = "onToggle";
private static final String ON_SWITCH_VIEW_EVENT = "onSwitchView";
private static final String ON_ACTIVATE_EVENT = "onActivate";
private static final String ON_SELECTION_CHANGED_EVENT = "onSelectionChanged";
public static final String ADTAB_INDEX_ATTRIBUTE = "adtab.index";
/** Logger */
@SuppressWarnings("unused")
private static CLogger log = CLogger.getCLogger (CompositeADTabbox.class);
private List<ADTabListModel.ADTabLabel> tabLabelList = new ArrayList<ADTabListModel.ADTabLabel>();
private List<IADTabpanel> tabPanelList = new ArrayList<IADTabpanel>();
private Vlayout layout;
protected DetailPane detailPane;
private EventListener<Event> selectionListener;
private IADTabpanel headerTab;
private int selectedIndex = 0;
public CompositeADTabbox()
{
detailPane = new DetailPane();
detailPane.setEventListener(new EventListener<Event>() {
@Override
public void onEvent(Event event) throws Exception {
if (DetailPane.ON_EDIT_EVENT.equals(event.getName())) {
final int row = detailPane.getSelectedADTabpanel() != null
? detailPane.getSelectedADTabpanel().getGridTab().getCurrentRow()
: 0;
adWindowPanel.saveAndNavigate(new Callback<Boolean>() {
@Override
public void onCallback(Boolean result) {
if (result)
onEditDetail(row);
}
});
}
else if (DetailPane.ON_NEW_EVENT.equals(event.getName())) {
final int row = detailPane.getSelectedADTabpanel() != null
? detailPane.getSelectedADTabpanel().getGridTab().getCurrentRow()
: 0;
adWindowPanel.saveAndNavigate(new Callback<Boolean>() {
@Override
public void onCallback(Boolean result) {
if (result) {
onEditDetail(row);
adWindowPanel.onNew();
}
}
});
}
else if (DetailPane.ON_DELETE_EVENT.equals(event.getName())) {
final IADTabpanel tabPanel = detailPane.getSelectedADTabpanel();
if (tabPanel != null && tabPanel.getGridTab().getRowCount() > 0
&& tabPanel.getGridTab().getCurrentRow() >= 0) {
FDialog.ask(tabPanel.getGridTab().getWindowNo(), null, "DeleteRecord?", new Callback<Boolean>() {
@Override
public void onCallback(Boolean result) {
if (!result) return;
if (!tabPanel.getGridTab().dataDelete()) {
showLastError();
} else {
adWindowPanel.onRefresh(false);
}
}
});
}
}
}
});
}
protected void onEditDetail(int row) {
int oldIndex = selectedIndex;
IADTabpanel selectedPanel = detailPane.getSelectedADTabpanel();
int newIndex = (Integer)selectedPanel.getAttribute(ADTAB_INDEX_ATTRIBUTE);
Event selectionChanged = new Event(ON_SELECTION_CHANGED_EVENT, layout, new Object[]{oldIndex, newIndex});
try {
selectionListener.onEvent(selectionChanged);
} catch (Exception e) {
throw new RuntimeException(e);
}
headerTab.setDetailPaneMode(false, true);
if (headerTab.isGridView()) {
headerTab.switchRowPresentation();
}
headerTab.getGridTab().setCurrentRow(row, true);
}
protected Component doCreatePart(Component parent)
{
layout = new Vlayout();
layout.setHeight("100%");
layout.setWidth("100%");
layout.setStyle("position: relative");
if (parent != null) {
layout.setParent(parent);
} else {
layout.setPage(page);
}
BreadCrumb breadCrumb = getBreadCrumb();
breadCrumb.addEventListener(Events.ON_CLICK, new EventListener<Event>() {
@Override
public void onEvent(Event event) throws Exception {
int oldIndex = selectedIndex;
if (event.getTarget() instanceof BreadCrumbLink) {
BreadCrumbLink link = (BreadCrumbLink) event.getTarget();
int newIndex = Integer.parseInt(link.getPathId());
Event selectionChanged = new Event(ON_SELECTION_CHANGED_EVENT, layout, new Object[]{oldIndex, newIndex});
selectionListener.onEvent(selectionChanged);
} else if (event.getTarget() instanceof Menuitem) {
Menuitem item = (Menuitem) event.getTarget();
int newIndex = Integer.parseInt(item.getValue());
Event selectionChanged = new Event(ON_SELECTION_CHANGED_EVENT, layout, new Object[]{oldIndex, newIndex});
selectionListener.onEvent(selectionChanged);
}
}
});
return layout;
}
@Override
protected void doAddTab(GridTab gTab, IADTabpanel tabPanel) {
ADTabListModel.ADTabLabel tabLabel = new ADTabListModel.ADTabLabel(gTab.getName(), gTab.getTabLevel(),gTab.getDescription(),
gTab.getWindowNo(),gTab.getAD_Tab_ID());
tabLabelList.add(tabLabel);
tabPanelList.add(tabPanel);
tabPanel.setAttribute(ADTAB_INDEX_ATTRIBUTE, tabPanelList.size()-1);
tabPanel.addEventListener(ON_ACTIVATE_EVENT, new EventListener<Event>() {
@Override
public void onEvent(Event event) throws Exception {
Boolean b = (Boolean) event.getData();
if (b != null && !b.booleanValue())
return;
IADTabpanel tabPanel = (IADTabpanel) event.getTarget();
if (tabPanel == headerTab) {
if (b != null && b.booleanValue()) {
activateDetailADTabpanel();
}
if (selectedIndex > 0 && tabPanel.isGridView()) {
tabPanel.switchRowPresentation();
}
} else {
onActivateDetail(tabPanel);
}
}
});
tabPanel.addEventListener(DetailPane.ON_ACTIVATE_DETAIL_EVENT, new EventListener<Event>() {
@Override
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 (prevTabPanel != null && prevTabPanel.getGridTab().needSave(true, true)) {
final int newIndex = detailPane.getSelectedIndex();
detailPane.setSelectedIndex(oldIndex);
adWindowPanel.saveAndNavigate(new Callback<Boolean>() {
@Override
public void onCallback(Boolean result) {
if (result) {
detailPane.setSelectedIndex(newIndex);
onActivateDetail(tabPanel);
}
}
});
} else {
onActivateDetail(tabPanel);
}
} else {
onActivateDetail(tabPanel);
}
}
});
tabPanel.addEventListener(ON_SWITCH_VIEW_EVENT, new EventListener<Event>() {
@Override
public void onEvent(Event event) throws Exception {
IADTabpanel tabPanel = (IADTabpanel) event.getTarget();
if (tabPanel == headerTab) {
IADTabpanel detailPanel = getSelectedDetailADTabpanel();
if (detailPanel != null) {
detailPanel.setDetailPaneMode(true, headerTab.isGridView());
}
detailPane.setVflex(Boolean.toString(headerTab.isGridView()));
layout.invalidate();
}
}
});
tabPanel.addEventListener(ON_TOGGLE_EVENT, new EventListener<Event>() {
@Override
public void onEvent(Event event) throws Exception {
IADTabpanel tabPanel = (IADTabpanel) event.getTarget();
if (tabPanel == headerTab) {
adWindowPanel.onToggle();
} else {
detailPane.onEdit();
}
}
});
if (layout.getChildren().isEmpty()) {
layout.appendChild(tabPanel);
headerTab = tabPanel;
updateBreadCrumb();
} else if (tabLabel.tabLevel <= 1) {
boolean activate = false;
if (detailPane.getParent() == null) {
ADTabpanel adtabpanel = (ADTabpanel) headerTab;
adtabpanel.addDetails(detailPane);
activate = true;
} else
tabPanel.setVisible(false);
detailPane.setHflex("1");
detailPane.setStyle("min-height: 200px; overflow-y: visible;");
detailPane.addADTabpanel(tabPanel, tabLabel);
tabPanel.setDetailPaneMode(true, headerTab.isGridView());
detailPane.setVflex(Boolean.toString(headerTab.isGridView()));
if (activate)
activateDetailADTabpanel();
} else {
detailPane.addADTabpanel(tabPanel, tabLabel, false);
tabPanel.setDetailPaneMode(true, headerTab.isGridView());
detailPane.setVflex(Boolean.toString(headerTab.isGridView()));
}
HtmlBasedComponent htmlComponent = (HtmlBasedComponent) tabPanel;
htmlComponent.setVflex("1");
htmlComponent.setWidth("100%");
tabPanel.getGridTab().addDataStatusListener(new SyncDataStatusListener(tabPanel));
}
protected void activateDetailADTabpanel() {
if (detailPane != null && detailPane.getParent() != null) {
IADTabpanel tabPanel = detailPane.getSelectedADTabpanel();
tabPanel.activate(true);
if (!tabPanel.isGridView()) {
tabPanel.switchRowPresentation();
}
}
}
/**
* Evaluate Tab Logic
* @param e event
*/
public void evaluate (DataStatusEvent e)
{
super.evaluate(e);
} // evaluate
@Override
protected void updateTabState() {
detailPane.refresh();
}
/**
* Return the selected Tab Panel
*/
public IADTabpanel getSelectedTabpanel()
{
return tabPanelList.isEmpty() ? null : tabPanelList.get(selectedIndex);
}
public int getSelectedIndex() {
return selectedIndex;
}
public void setSelectionEventListener(EventListener<Event> listener) {
selectionListener = listener;
}
@Override
protected void doTabSelectionChanged(int oldIndex, int newIndex) {
selectedIndex = newIndex;
IADTabpanel oldTabpanel = oldIndex >= 0 ? tabPanelList.get(oldIndex) : null;
IADTabpanel newTabpanel = tabPanelList.get(newIndex);
if (oldTabpanel != null) {
oldTabpanel.setVisible(false);
}
newTabpanel.createUI();
newTabpanel.setVisible(true);
headerTab = newTabpanel;
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, headerTab.isGridView());
} else if (tabLevel > currentLevel ){
detailPane.addADTabpanel(tabPanel, tabLabel, false);
tabPanel.setDetailPaneMode(true, headerTab.isGridView());
}
}
if (detailPane.getTabcount() > 0 && !headerTab.getGridTab().isSortTab()) {
ADTabpanel adtabpanel = (ADTabpanel) headerTab;
adtabpanel.addDetails(detailPane);
detailPane.setVflex(Boolean.toString(headerTab.isGridView()));
detailPane.setSelectedIndex(0);
}
updateBreadCrumb();
}
private void updateBreadCrumb() {
BreadCrumb breadCrumb = getBreadCrumb();
breadCrumb.reset();
if (selectedIndex > 0) {
List<ADTabLabel> parents = new ArrayList<ADTabListModel.ADTabLabel>();
List<Integer> parentIndex = new ArrayList<Integer>();
int currentLevel = headerTab.getTabLevel();
for(int i = selectedIndex - 1; i >= 0; i--) {
ADTabLabel tabLabel = tabLabelList.get(i);
if (tabLabel.tabLevel == currentLevel-1) {
parents.add(tabLabel);
parentIndex.add(i);
currentLevel = tabLabel.tabLevel;
}
}
Collections.reverse(parents);
Collections.reverse(parentIndex);
for(ADTabLabel tabLabel : parents) {
int index = parentIndex.remove(0);
breadCrumb.addPath(tabLabel.label, Integer.toString(index), true);
}
}
ADTabLabel tabLabel = tabLabelList.get(selectedIndex);
breadCrumb.addPath(tabLabel.label, Integer.toString(selectedIndex), false);
breadCrumb.setVisible(true);
LinkedHashMap<String, String> links = new LinkedHashMap<String, String>();
int parentIndex = 0;
if (headerTab.getTabLevel() > 1) {
for(int i = selectedIndex - 1; i > 0; i--) {
tabLabel = tabLabelList.get(i);
if (tabLabel.tabLevel == (headerTab.getTabLevel()-1)) {
parentIndex = i;
break;
}
}
}
for(int i = parentIndex+1; i < tabLabelList.size(); i++) {
if (i == selectedIndex) continue;
tabLabel = tabLabelList.get(i);
if (tabLabel.tabLevel == headerTab.getTabLevel()) {
links.put(Integer.toString(i), tabLabel.label);
} else if (tabLabel.tabLevel < headerTab.getTabLevel()) {
break;
}
}
if (!links.isEmpty()) {
breadCrumb.addLinks(links);
}
}
protected BreadCrumb getBreadCrumb() {
ADWindowContent window = (ADWindowContent) adWindowPanel;
BreadCrumb breadCrumb = window.getBreadCrumb();
return breadCrumb;
}
public Component getComponent() {
return layout;
}
@Override
public IADTabpanel findADTabpanel(GridTab gTab) {
for (IADTabpanel tabpanel : tabPanelList) {
if (tabpanel.getGridTab() == gTab) {
return tabpanel;
}
}
return null;
}
public void refresh() {
}
class SyncDataStatusListener implements DataStatusListener {
private IADTabpanel tabPanel;
SyncDataStatusListener(IADTabpanel tabpanel) {
this.tabPanel = tabpanel;
}
@Override
public void dataStatusChanged(DataStatusEvent e) {
Execution execution = Executions.getCurrent();
if (execution == null) return;
if (tabPanel == headerTab && detailPane.getPage() != null && e.getChangedColumn() == -1) {
ArrayList<String> parentColumnNames = new ArrayList<String>();
GridField[] parentFields = headerTab.getGridTab().getFields();
for (GridField parentField : parentFields) {
parentColumnNames.add(parentField.getColumnName());
}
IADTabpanel detailTab = detailPane.getSelectedADTabpanel();
//check data action
String uuid = (String) execution.getAttribute(CompositeADTabbox.class.getName()+".dataAction");
if (uuid != null && uuid.equals(detailTab.getUuid())) {
//refresh current row
detailTab.getGridTab().dataRefresh(false);
//keep focus
onDetailRecord();
return;
}
GridTab tab = detailTab.getGridTab();
GridField[] fields = tab.getFields();
for (GridField field : fields)
{
if (!parentColumnNames.contains(field.getColumnName()))
Env.setContext(Env.getCtx(), field.getWindowNo(), field.getColumnName(), "");
}
detailTab.query(false, 0, 0);
detailTab.activate(true);
detailTab.setDetailPaneMode(true, headerTab.isGridView());
detailPane.setVflex(Boolean.toString(headerTab.isGridView()));
}
}
}
@Override
public void onDetailRecord() {
if (detailPane != null && detailPane.getParent() != null) {
Clients.scrollIntoView(detailPane);
detailPane.focus();
}
}
@Override
public void onParentRecord() {
Clients.scrollIntoView(headerTab);
((HtmlBasedComponent)headerTab).focus();
}
@Override
public boolean isSortTab() {
return headerTab != null ? headerTab.getGridTab().isSortTab() : false;
}
@Override
public IADTabpanel getSelectedDetailADTabpanel() {
if (detailPane != null && detailPane.getParent() != null) {
return detailPane.getSelectedADTabpanel();
}
return null;
}
@Override
public boolean needSave(boolean rowChange, boolean onlyRealChange) {
boolean b = headerTab.getGridTab().needSave(rowChange, onlyRealChange);
if (b)
return b;
IADTabpanel detailPanel = getSelectedDetailADTabpanel();
if (detailPanel != null) {
b = detailPanel.getGridTab().needSave(rowChange, onlyRealChange);
}
return b;
}
@Override
public void dataIgnore() {
IADTabpanel detailPanel = getSelectedDetailADTabpanel();
if (detailPanel != null) {
detailPanel.getGridTab().dataIgnore();
}
headerTab.getGridTab().dataIgnore();
}
@Override
public GridTab getSelectedGridTab() {
IADTabpanel tabpanel = getSelectedTabpanel();
return tabpanel == null ? null : tabpanel.getGridTab();
}
@Override
public boolean dataSave(boolean onSaveEvent) {
IADTabpanel detail = getSelectedDetailADTabpanel();
if (detail != null && detail.getGridTab().needSave(true, true)) {
Execution execution = Executions.getCurrent();
if (execution != null) {
execution.setAttribute(getClass().getName()+".dataAction", detail.getUuid());
}
return detail.getGridTab().dataSave(onSaveEvent);
}
return headerTab.getGridTab().dataSave(onSaveEvent);
}
@Override
public void setDetailPaneStatusMessage(String status, boolean error) {
detailPane.setStatusMessage(status, error);
}
@Override
public IADTabpanel getDirtyADTabpanel() {
IADTabpanel detail = getSelectedDetailADTabpanel();
if (detail != null && detail.getGridTab().needSave(true, true)) {
return detail;
} else if (detail != null && detail instanceof ADSortTab && ((ADSortTab)detail).isChanged()) {
return detail;
} else if (headerTab.getGridTab().needSave(true, true)) {
return headerTab;
} else if (headerTab instanceof ADSortTab && ((ADSortTab)headerTab).isChanged()) {
return headerTab;
}
return null;
}
protected void onActivateDetail(IADTabpanel tabPanel) {
tabPanel.createUI();
tabPanel.query(false, 0, 0);
if (!tabPanel.isVisible())
tabPanel.setVisible(true);
if (!tabPanel.isGridView()) {
tabPanel.switchRowPresentation();
}
tabPanel.setDetailPaneMode(true, headerTab.isGridView());
detailPane.setVflex(Boolean.toString(headerTab.isGridView()));
if (tabPanel instanceof ADSortTab) {
detailPane.invalidate();
detailPane.updateToolbar(false, true);
onDetailRecord();
}
}
private void showLastError() {
String msg = CLogger.retrieveErrorString(null);
if (msg != null)
{
detailPane.setStatusMessage(Msg.getMsg(Env.getCtx(), msg), true);
}
//other error will be catch in the dataStatusChanged event
}
@Override
public void updateDetailPaneToolbar(boolean changed, boolean readOnly) {
detailPane.updateToolbar(changed, readOnly);
}
}

View File

@ -0,0 +1,414 @@
/**
*
*/
package org.adempiere.webui.adwindow;
import java.util.HashMap;
import java.util.Map;
import org.adempiere.webui.LayoutUtils;
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;
import org.adempiere.webui.component.ADTabListModel.ADTabLabel;
import org.adempiere.webui.session.SessionManager;
import org.compiere.util.Env;
import org.compiere.util.Msg;
import org.compiere.util.Util;
import org.zkoss.zhtml.Text;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Execution;
import org.zkoss.zk.ui.Executions;
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.util.Clients;
import org.zkoss.zul.Caption;
import org.zkoss.zul.Div;
import org.zkoss.zul.Hbox;
import org.zkoss.zul.Image;
import org.zkoss.zul.Space;
import org.zkoss.zul.Tabpanels;
import org.zkoss.zul.Tabs;
import org.zkoss.zul.Toolbar;
/**
* @author hengsin
*
*/
public class DetailPane extends Panel implements EventListener<Event> {
private static final String STATUS_TEXT_ATTRIBUTE = "status.text";
private static final String STATUS_ERROR_ATTRIBUTE = "status.error";
private static final String TABBOX_STYLE = "min-height: 200px; overflow-y: visible; width: 99%; margin: auto;";
private static final String DELETE_IMAGE = "/images/Delete16.png";
private static final String EDIT_IMAGE = "/images/EditRecord16.png";
private static final String NEW_IMAGE = "/images/New16.png";
private static final String STYLE = "min-height: 200px; width: 100%; overflow-y: visible;";
/**
* generated serial id
*/
private static final long serialVersionUID = -7914602940626352282L;
private static final String INFO_INDICATOR_IMAGE = "/images/InfoIndicator16.png";
private static final String ERROR_INDICATOR_IMAGE = "/images/ErrorIndicator16.png";
private Tabbox tabbox;
private EventListener<Event> eventListener;
private Map<Integer, Hbox> messageContainers = new HashMap<Integer, Hbox>();
private Div msgPopupCnt;
private Window msgPopup;
private Caption msgPopupCaption;
private int prevSelectedIndex = 0;
public static final String ON_ACTIVATE_DETAIL_EVENT = "onActivateDetail";
public static final String ON_DELETE_EVENT = "onDelete";
public static final String ON_NEW_EVENT = "onNew";
public static final String ON_EDIT_EVENT = "onEdit";
public DetailPane() {
tabbox = new Tabbox();
tabbox.setParent(this);
tabbox.addEventListener(Events.ON_SELECT, new EventListener<Event>() {
@Override
public void onEvent(Event event) throws Exception {
int index = tabbox.getSelectedIndex();
IADTabpanel tabPanel = (IADTabpanel) tabbox.getTabpanel(index).getChildren().get(1);
Event activateEvent = new Event(ON_ACTIVATE_DETAIL_EVENT, tabPanel, prevSelectedIndex);
Events.sendEvent(activateEvent);
}
});
tabbox.setStyle(TABBOX_STYLE);
createPopup();
this.setStyle(STYLE);
//TODO: this probably not needed
this.setHflex("true");
}
public int getSelectedIndex() {
return tabbox.getSelectedIndex();
}
public void setSelectedIndex(int curTabIndex) {
tabbox.setSelectedIndex(curTabIndex);
prevSelectedIndex = curTabIndex;
}
public int getTabcount() {
int count = 0;
Tabs tabs = tabbox.getTabs();
if (tabs != null)
count = tabs.getChildren().size();
return count;
}
public void undoLastTabSelection() {
tabbox.setSelectedIndex(prevSelectedIndex);
}
public void refresh() {
tabbox.invalidate();
}
public void addADTabpanel(IADTabpanel tabPanel, ADTabLabel tabLabel) {
addADTabpanel(tabPanel, tabLabel, true);
}
public void addADTabpanel(IADTabpanel tabPanel, ADTabLabel tabLabel, boolean enabled) {
Tabs tabs = tabbox.getTabs();
if (tabs == null) {
tabs = new Tabs();
tabbox.appendChild(tabs);
}
Tab tab = new Tab();
tabs.appendChild(tab);
tab.setLabel(tabLabel.label);
if (!enabled) {
tab.setDisabled(true);
}
Tabpanels tabpanels = tabbox.getTabpanels();
if (tabpanels == null) {
tabpanels = new Tabpanels();
//TODO: is this style needed ?
tabpanels.setStyle("min-height: 200px; overflow-y: visible;");
tabpanels.setWidth("100%");
tabbox.appendChild(tabpanels);
}
Tabpanel tp = new Tabpanel();
//TODO: is this style needed
tp.setStyle("min-height: 180px; overflow-y: visible; width: 99%; margin: auto;");
tabpanels.appendChild(tp);
tp.setStyle("background-color: #fff");
ToolBar toolbar = new ToolBar();
tp.appendChild(toolbar);
ToolBarButton button = new ToolBarButton();
button = new ToolBarButton();
button.setImage(NEW_IMAGE);
toolbar.appendChild(button);
button.addEventListener(Events.ON_CLICK, new EventListener<Event>() {
@Override
public void onEvent(Event event) throws Exception {
Event openEvent = new Event(ON_NEW_EVENT, DetailPane.this);
eventListener.onEvent(openEvent);
}
});
button.setTooltiptext(Util.cleanAmp(Msg.getMsg(Env.getCtx(), "New")));
button = new ToolBarButton();
button.setImage(EDIT_IMAGE);
toolbar.appendChild(button);
button.addEventListener(Events.ON_CLICK, new EventListener<Event>() {
@Override
public void onEvent(Event event) throws Exception {
onEdit();
}
});
button.setTooltiptext(Util.cleanAmp(Msg.getMsg(Env.getCtx(), "EditRecord")));
button = new ToolBarButton();
button.setImage(DELETE_IMAGE);
toolbar.appendChild(button);
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);
}
});
button.setTooltiptext(Util.cleanAmp(Msg.getMsg(Env.getCtx(), "Delete")));
Hbox messageContainer = new Hbox();
messageContainer.setPack("end");
messageContainer.setHflex("1");
messageContainer.setStyle("float: right");
toolbar.appendChild(messageContainer);
toolbar.setSclass("adtab-detail-toolbar");
toolbar.setVflex("0");
messageContainers.put(tabLabel.AD_Tab_ID, messageContainer);
tabPanel.setAttribute("AD_Tab_ID", tabLabel.AD_Tab_ID);
tp.appendChild(tabPanel);
}
public void setEventListener(EventListener<Event> listener) {
eventListener = listener;
}
public void reset() {
if (tabbox.getTabs() != null) {
tabbox.getTabs().getChildren().clear();
}
if (tabbox.getTabpanels() != null) {
tabbox.getTabpanels().getChildren().clear();
}
}
public IADTabpanel getADTabpanel(int index) {
if (index < 0 || index >= tabbox.getTabpanels().getChildren().size())
return null;
org.zkoss.zul.Tabpanel tabPanel = tabbox.getTabpanel(index);
for(Component c : tabPanel.getChildren()) {
if (c instanceof IADTabpanel)
return (IADTabpanel)c;
}
return null;
}
public IADTabpanel getSelectedADTabpanel() {
org.zkoss.zul.Tabpanel selectedPanel = tabbox.getSelectedPanel();
if (selectedPanel != null) {
for(Component c : selectedPanel.getChildren()) {
if (c instanceof IADTabpanel)
return (IADTabpanel)c;
}
}
return null;
}
public void setStatusMessage(String status, boolean error) {
IADTabpanel tabPanel = getSelectedADTabpanel();
Hbox messageContainer = messageContainers.get(tabPanel.getAttribute("AD_Tab_ID"));
Execution execution = Executions.getCurrent();
if (execution != null) {
String key = this.getClass().getName()+"."+messageContainer.getUuid();
Object o = execution.getAttribute(key);
if (o != null) {
if (status == null || status.trim().length() == 0)
return;
} else {
execution.setAttribute(key, Boolean.TRUE);
}
}
messageContainer.getChildren().clear();
messageContainer.setAttribute(STATUS_ERROR_ATTRIBUTE, error);
messageContainer.setAttribute(STATUS_TEXT_ATTRIBUTE, status);
if (status == null || status.trim().length() == 0)
return;
Image image = null;
if (error)
image = new Image(ERROR_INDICATOR_IMAGE);
else
image = new Image(INFO_INDICATOR_IMAGE);
image.setAttribute("org.zkoss.zul.image.preload", Boolean.TRUE);
messageContainer.appendChild(image);
String labelText = buildLabelText(status);
if (error) {
Clients.showNotification(labelText, "error", image, "overlap_start", 3500, true);
}
Label label = new Label(labelText);
messageContainer.appendChild(label);
if (labelText.length() != status.length()) {
image.addEventListener(Events.ON_CLICK, this);
image.setStyle("cursor: pointer");
label.addEventListener(Events.ON_CLICK, this);
label.setStyle("cursor: pointer");
label = new Label(" ...");
label.setStyle("cursor: pointer");
messageContainer.appendChild(label);
label.addEventListener(Events.ON_CLICK, this);
}
messageContainer.appendChild(new Space());
}
private String buildLabelText(String statusText) {
if (statusText == null)
return "";
if (statusText.length() <= 80)
return statusText;
int index = statusText.indexOf(" - java.lang.Exception");
if (index > 0)
return statusText.substring(0, index);
return statusText.substring(0, 80);
}
@Override
public void onEvent(Event event) throws Exception {
Component messageContainer = event.getTarget().getParent();
Boolean error = (Boolean) messageContainer.getAttribute(STATUS_ERROR_ATTRIBUTE);
String status = (String) messageContainer.getAttribute(STATUS_TEXT_ATTRIBUTE);
createPopupContent(status);
showPopup(error, messageContainer);
}
protected void createPopupContent(String status) {
Text t = new Text(status);
msgPopupCnt.getChildren().clear();
msgPopupCnt.appendChild(t);
}
private void showPopup(boolean error, Component messageContainer) {
msgPopupCaption.setImage(error ? ERROR_INDICATOR_IMAGE : INFO_INDICATOR_IMAGE);
LayoutUtils.openOverlappedWindow(messageContainer, msgPopup, "overlap_end");
}
private void createPopup() {
msgPopupCnt = new Div();
msgPopupCnt.setVflex("1");
msgPopup = new Window();
msgPopup.setBorder(true);
msgPopup.setClosable(true);
msgPopup.setSizable(true);
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);
}
@Override
public void onPageDetached(Page page) {
super.onPageDetached(page);
if (msgPopup != null)
msgPopup.detach();
}
/* (non-Javadoc)
* @see org.zkoss.zk.ui.HtmlBasedComponent#setVflex(java.lang.String)
*/
@Override
public void setVflex(String flex) {
super.setVflex(flex);
tabbox.setVflex(flex);
}
public void updateToolbar(boolean changed, boolean readOnly) {
int index = getSelectedIndex();
if (index < 0 || index >= getTabcount()) return;
Tabpanel tabpanel = tabbox.getTabpanel(index);
Toolbar toolbar = (Toolbar) tabpanel.getFirstChild();
IADTabpanel adtab = getADTabpanel(index);
if (adtab.getGridTab().isSortTab())
readOnly = true;
boolean insertRecord = !readOnly;
if (insertRecord)
{
insertRecord = adtab.getGridTab().isInsertRecord();
}
boolean enableNew = !changed && insertRecord && !adtab.getGridTab().isSortTab();
boolean enableDelete = !changed && !readOnly && !adtab.getGridTab().isSortTab();
int newBtn = 0;
int deleteBtn = 0;
for(Component c : toolbar.getChildren()) {
if (c instanceof ToolBarButton) {
ToolBarButton btn = (ToolBarButton) c;
if (NEW_IMAGE.equals(btn.getImage())) {
btn.setDisabled(!enableNew);
newBtn++;
} else if (DELETE_IMAGE.equals(btn.getImage())) {
btn.setDisabled(!enableDelete);
deleteBtn++;
}
if (newBtn > 0 && deleteBtn > 0)
break;
}
}
}
public void onEdit() throws Exception {
Event openEvent = new Event(ON_EDIT_EVENT, DetailPane.this);
eventListener.onEvent(openEvent);
}
}

View File

@ -10,7 +10,7 @@
* with this program; if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
*****************************************************************************/
package org.adempiere.webui.component;
package org.adempiere.webui.adwindow;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
@ -23,6 +23,9 @@ import java.util.Map.Entry;
import org.adempiere.util.GridRowCtx;
import org.adempiere.webui.apps.AEnv;
import org.adempiere.webui.component.Checkbox;
import org.adempiere.webui.component.EditorBox;
import org.adempiere.webui.component.NumberBox;
import org.adempiere.webui.editor.WButtonEditor;
import org.adempiere.webui.editor.WEditor;
import org.adempiere.webui.editor.WEditorPopupMenu;
@ -30,10 +33,8 @@ import org.adempiere.webui.editor.WebEditorFactory;
import org.adempiere.webui.event.ActionEvent;
import org.adempiere.webui.event.ActionListener;
import org.adempiere.webui.event.ContextMenuListener;
import org.adempiere.webui.panel.AbstractADWindowPanel;
import org.adempiere.webui.session.SessionManager;
import org.adempiere.webui.util.GridTabDataBinder;
import org.adempiere.webui.window.ADWindow;
import org.compiere.model.GridField;
import org.compiere.model.GridTab;
import org.compiere.util.DisplayType;
@ -80,12 +81,12 @@ public class GridTabRowRenderer implements RowRenderer<Object[]>, RowRendererExt
private RowListener rowListener;
private Grid grid = null;
private GridPanel gridPanel = null;
private GridView gridPanel = null;
private Row currentRow;
private Object[] currentValues;
private boolean editing = false;
private int currentRowIndex = -1;
private AbstractADWindowPanel m_windowPanel;
private AbstractADWindowContent m_windowPanel;
/**
*
@ -122,7 +123,7 @@ public class GridTabRowRenderer implements RowRenderer<Object[]>, RowRendererExt
Object window = SessionManager.getAppDesktop().findWindow(windowNo);
if (window != null && window instanceof ADWindow)
{
AbstractADWindowPanel windowPanel = ((ADWindow)window).getADWindowPanel();
AbstractADWindowContent windowPanel = ((ADWindow)window).getADWindowContent();
((WButtonEditor)editor).addActionListener(windowPanel);
}
}
@ -625,7 +626,7 @@ public class GridTabRowRenderer implements RowRenderer<Object[]>, RowRendererExt
*
* @param gridPanel
*/
public void setGridPanel(GridPanel gridPanel) {
public void setGridPanel(GridView gridPanel) {
this.gridPanel = gridPanel;
}
@ -664,7 +665,7 @@ public class GridTabRowRenderer implements RowRenderer<Object[]>, RowRendererExt
/**
* @param windowPanel
*/
public void setADWindowPanel(AbstractADWindowPanel windowPanel) {
public void setADWindowPanel(AbstractADWindowContent windowPanel) {
this.m_windowPanel = windowPanel;
}
}

View File

@ -10,7 +10,7 @@
* with this program; if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
*****************************************************************************/
package org.adempiere.webui.component;
package org.adempiere.webui.adwindow;
import java.util.Comparator;

View File

@ -10,7 +10,7 @@
* with this program; if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
*****************************************************************************/
package org.adempiere.webui.component;
package org.adempiere.webui.adwindow;
import java.util.ArrayList;
import java.util.Collections;
@ -22,11 +22,14 @@ import java.util.Map;
import javax.swing.table.AbstractTableModel;
import org.adempiere.model.MTabCustomization;
import org.adempiere.webui.LayoutUtils;
import org.adempiere.webui.apps.AEnv;
import org.adempiere.webui.component.Borderlayout;
import org.adempiere.webui.component.Columns;
import org.adempiere.webui.component.EditorBox;
import org.adempiere.webui.component.Grid;
import org.adempiere.webui.component.NumberBox;
import org.adempiere.webui.editor.WEditor;
import org.adempiere.webui.event.TouchEventHelper;
import org.adempiere.webui.panel.AbstractADWindowPanel;
import org.adempiere.webui.util.SortComparator;
import org.compiere.model.GridField;
import org.compiere.model.GridTab;
@ -34,6 +37,8 @@ import org.compiere.model.GridTable;
import org.compiere.model.MSysConfig;
import org.compiere.util.DisplayType;
import org.compiere.util.Env;
import org.compiere.util.Msg;
import org.compiere.util.Util;
import org.zkoss.zk.au.out.AuFocus;
import org.zkoss.zk.au.out.AuScript;
import org.zkoss.zk.ui.AbstractComponent;
@ -42,14 +47,14 @@ 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.Borderlayout;
import org.zkoss.zul.Center;
import org.zkoss.zul.Frozen;
import org.zkoss.zul.South;
import org.zkoss.zul.Column;
import org.zkoss.zul.Div;
import org.zkoss.zul.North;
import org.zkoss.zul.Paging;
import org.zkoss.zul.Row;
import org.zkoss.zul.Vbox;
import org.zkoss.zul.event.ZulEvents;
/**
@ -57,8 +62,12 @@ import org.zkoss.zul.event.ZulEvents;
* @author Low Heng Sin
*
*/
public class GridPanel extends Borderlayout implements EventListener<Event>
public class GridView extends Vbox implements EventListener<Event>
{
private static final int DEFAULT_DETAIL_PAGE_SIZE = 10;
private static final int DEFAULT_PAGE_SIZE = 50;
/**
* generated serial version ID
*/
@ -74,7 +83,7 @@ public class GridPanel extends Borderlayout implements EventListener<Event>
private Grid listbox = null;
private int pageSize = 100;
private int pageSize = DEFAULT_PAGE_SIZE;
private GridField[] gridField;
private AbstractTableModel tableModel;
@ -93,19 +102,23 @@ public class GridPanel extends Borderlayout implements EventListener<Event>
private GridTabRowRenderer renderer;
private South south;
private Div gridFooter;
private boolean modeless = true;
private String columnOnClick;
private AbstractADWindowPanel windowPanel;
private AbstractADWindowContent windowPanel;
private boolean refreshing;
private Map<Integer, String> columnWidthMap;
public GridPanel()
private Component detail;
private Borderlayout borderLayout;
public GridView()
{
this(0);
}
@ -113,14 +126,29 @@ public class GridPanel extends Borderlayout implements EventListener<Event>
/**
* @param windowNo
*/
public GridPanel(int windowNo)
public GridView(int windowNo)
{
this.windowNo = windowNo;
listbox = new Grid();
listbox.addEventListener(ZulEvents.ON_AFTER_RENDER, this);
south = new South();
this.appendChild(south);
createListbox();
this.setHflex("1");
gridFooter = new Div();
gridFooter.setHflex("1");
gridFooter.setVflex("0");
borderLayout = new Borderlayout();
borderLayout.setStyle("position: absolute; height: 100%; width: 100%;");
appendChild(borderLayout);
Center center = new Center();
borderLayout.appendChild(center);
North north = new North();
north.setVflex("min");
borderLayout.appendChild(north);
borderLayout.appendCenter(listbox);
borderLayout.appendNorth(gridFooter);
//default paging size
if (AEnv.isTablet())
{
@ -129,7 +157,7 @@ public class GridPanel extends Borderlayout implements EventListener<Event>
}
else
{
pageSize = MSysConfig.getIntValue(MSysConfig.ZK_PAGING_SIZE, 100);
pageSize = MSysConfig.getIntValue(MSysConfig.ZK_PAGING_SIZE, 50);
}
//default true for better UI experience
@ -137,6 +165,51 @@ public class GridPanel extends Borderlayout implements EventListener<Event>
}
protected void createListbox() {
listbox = new Grid();
listbox.setEmptyMessage(Util.cleanAmp(Msg.getMsg(Env.getCtx(), "FindZeroRecords")));
listbox.addEventListener(ZulEvents.ON_AFTER_RENDER, this);
listbox.setSizedByContent(true);
listbox.setVflex("1");
listbox.setHflex("1");
}
public void setDetailPaneMode(boolean detailPaneMode, boolean vflex) {
if (detailPaneMode) {
pageSize = DEFAULT_DETAIL_PAGE_SIZE;
updatePaging();
if (borderLayout.getParent() != null) {
listbox.detach();
gridFooter.detach();
borderLayout.detach();
appendChild(listbox);
appendChild(gridFooter);
}
//false work for header form, true work for header grid
listbox.setVflex(vflex);
this.setVflex(Boolean.toString(vflex));
} else {
pageSize = MSysConfig.getIntValue(MSysConfig.ZK_PAGING_SIZE, 50);
updatePaging();
if (borderLayout.getParent() == null) {
listbox.detach();
gridFooter.detach();
appendChild(borderLayout);
borderLayout.appendCenter(listbox);
borderLayout.appendNorth(gridFooter);
}
listbox.setVflex("true");
this.setVflex("true");
}
}
private void updatePaging() {
if (paging != null && paging.getPageSize() != pageSize) {
paging.setPageSize(pageSize);
updateModel();
}
}
/**
*
* @param gridTab
@ -260,6 +333,10 @@ public class GridPanel extends Borderlayout implements EventListener<Event>
if (pageSize > 0) {
if (paging.getTotalSize() != gridTab.getRowCount())
paging.setTotalSize(gridTab.getRowCount());
if (paging.getPageCount() > 1 && !gridFooter.isVisible()) {
gridFooter.setVisible(true);
borderLayout.invalidate();
}
int pgIndex = rowIndex >= 0 ? rowIndex % pageSize : 0;
int pgNo = rowIndex >= 0 ? (rowIndex - pgIndex) / pageSize : 0;
if (listModel.getPage() != pgNo) {
@ -282,6 +359,11 @@ public class GridPanel extends Borderlayout implements EventListener<Event>
if (paging.getActivePage() != pgNo) {
paging.setActivePage(pgNo);
}
if (paging.getPageCount() == 1) {
gridFooter.setVisible(false);
} else {
gridFooter.setVisible(true);
}
if (rowIndex >= 0 && pgIndex >= 0) {
Events.echoEvent("onPostSelectedRowChanged", this, null);
}
@ -389,36 +471,29 @@ public class GridPanel extends Borderlayout implements EventListener<Event>
private void render()
{
LayoutUtils.addSclass("adtab-grid-panel", this);
listbox.setVflex(true);
//true might looks better, false for better performance
listbox.setSizedByContent(false);
listbox.addEventListener(Events.ON_CLICK, this);
updateModel();
Center center = new Center();
center.appendChild(listbox);
if (AEnv.isTablet()) {
LayoutUtils.addSclass("tablet-scrolling", center);
}
this.appendChild(center);
if (pageSize > 0)
{
paging = new Paging();
paging.setPageSize(pageSize);
paging.setTotalSize(tableModel.getRowCount());
paging.setDetailed(true);
south.appendChild(paging);
south.setSclass("adtab-grid-south");
gridFooter.appendChild(paging);
gridFooter.setSclass("adtab-grid-south");
paging.addEventListener(ZulEvents.ON_PAGING, this);
renderer.setPaging(paging);
if (paging.getPageCount() == 1) {
gridFooter.setVisible(false);
} else {
gridFooter.setVisible(true);
}
}
else
{
south.setVisible(false);
gridFooter.setVisible(false);
}
if (AEnv.isTablet()) {
@ -531,8 +606,6 @@ public class GridPanel extends Borderlayout implements EventListener<Event>
if (!isRowRendered(row, pgIndex)) {
listbox.renderRow(row);
} else {
// Row old = renderer.getCurrentRow();
// int oldIndex = renderer.getCurrentRowIndex();
renderer.setCurrentRow(row);
//remark: following 3 line cause the previously selected row being render twice
// if (old != null && old != row && oldIndex >= 0 && oldIndex != gridTab.getCurrentRow())
@ -556,8 +629,6 @@ public class GridPanel extends Borderlayout implements EventListener<Event>
if (!isRowRendered(row, rowIndex)) {
listbox.renderRow(row);
} else {
// Row old = renderer.getCurrentRow();
// int oldIndex = renderer.getCurrentRowIndex();
renderer.setCurrentRow(row);
//remark: following 3 line cause the previously selected row being render twice
// if (old != null && old != row && oldIndex >= 0 && oldIndex != gridTab.getCurrentRow())
@ -758,7 +829,7 @@ public class GridPanel extends Borderlayout implements EventListener<Event>
/**
* @param winPanel
*/
public void setADWindowPanel(AbstractADWindowPanel winPanel) {
public void setADWindowPanel(AbstractADWindowContent winPanel) {
windowPanel = winPanel;
if (renderer != null)
renderer.setADWindowPanel(windowPanel);
@ -782,4 +853,25 @@ public class GridPanel extends Borderlayout implements EventListener<Event>
public GridField[] getFields() {
return gridField;
}
public void addDetails(Component component) {
detail = component;
borderLayout.appendSouth(detail);
borderLayout.getSouth().setCollapsible(true);
borderLayout.getSouth().setTitle(Util.cleanAmp(Msg.getMsg(Env.getCtx(), "Detail")));
borderLayout.getSouth().setOpen(false);
borderLayout.getSouth().setHeight("250px");
}
public Component removeDetails() {
Component details = null;
if (detail != null) {
if (detail.getParent() != null) {
detail.detach();
details = detail;
}
detail = null;
}
return details;
}
}

View File

@ -10,14 +10,12 @@
* with this program; if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
*****************************************************************************/
package org.adempiere.webui.component;
package org.adempiere.webui.adwindow;
import org.adempiere.webui.panel.AbstractADWindowPanel;
import org.adempiere.webui.panel.IADTabpanel;
import org.adempiere.webui.part.UIPart;
import org.compiere.model.DataStatusEvent;
import org.compiere.model.GridTab;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
/**
@ -25,7 +23,7 @@ import org.zkoss.zk.ui.event.EventListener;
* @author <a href="mailto:hengsin@gmail.com">Low Heng Sin</a>
*
*/
public interface IADTab extends UIPart {
public interface IADTabbox extends UIPart {
/**
*
@ -91,17 +89,7 @@ public interface IADTab extends UIPart {
*
* @param listener
*/
public void addSelectionEventListener(EventListener listener);
/**
* @return tab selection component
*/
public Component getTabSelectionComponent();
/**
* @return boolean
*/
public boolean isUseExternalSelection();
public void setSelectionEventListener(EventListener<Event> listener);
/**
* @param index
@ -109,18 +97,6 @@ public interface IADTab extends UIPart {
*/
public IADTabpanel getADTabpanel(int index);
/**
* constant for tab placement
*/
public final int LEFT = 0;
public final int RIGHT = 1;
/**
* Set tab placement ( left or right )
* @param tabPlacement
*/
public void setTabplacement(int tabPlacement);
/**
* @param gTab
* @return IADTabpanel or null if not found
@ -131,5 +107,29 @@ public interface IADTab extends UIPart {
*
* @param abstractADWindowPanel
*/
public void setADWindowPanel(AbstractADWindowPanel abstractADWindowPanel);
public void setADWindowPanel(AbstractADWindowContent abstractADWindowPanel);
public void onDetailRecord();
public void onParentRecord();
public boolean isSortTab();
public boolean needSave(boolean rowChange, boolean onlyRealChange);
public void dataIgnore();
public GridTab getSelectedGridTab();
public boolean dataSave(boolean onSaveEvent);
public void refresh();
public void setDetailPaneStatusMessage(String status, boolean error);
IADTabpanel getSelectedDetailADTabpanel();
IADTabpanel getDirtyADTabpanel();
public void updateDetailPaneToolbar(boolean changed, boolean readOnly);
}

View File

@ -10,7 +10,7 @@
* with this program; if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
*****************************************************************************/
package org.adempiere.webui.panel;
package org.adempiere.webui.adwindow;
import org.compiere.model.GridTab;
import org.compiere.util.Evaluatee;
@ -101,4 +101,13 @@ public interface IADTabpanel extends Component, Evaluatee {
* @return true if the event is process
*/
public boolean onEnterKey();
/**
* @return boolean
*/
public boolean isGridView();
public boolean isActive();
public void setDetailPaneMode(boolean detailMode, boolean vflex);
}

View File

@ -0,0 +1,90 @@
/******************************************************************************
. * 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.adwindow;
import org.adempiere.webui.LayoutUtils;
import org.adempiere.webui.component.Label;
import org.adempiere.webui.component.Panel;
import org.zkoss.zul.Cell;
import org.zkoss.zul.Div;
import org.zkoss.zul.Hbox;
import org.zkoss.zul.Vbox;
/**
* This class is based on org.compiere.apps.StatusBar written by Jorg Janke.
* @author Jorg Janke
*
* @author <a href="mailto:agramdass@gmail.com">Ashley G Ramdass</a>
* @date Mar 12, 2007
* @version $Revision: 0.10 $
*/
public class StatusBar extends Panel
{
/**
*
*/
private static final long serialVersionUID = -3262889055635240201L;
private Label infoLine;
private Div west;
public StatusBar()
{
super();
init();
}
private void init()
{
Hbox hbox = new Hbox();
hbox.setWidth("100%");
hbox.setHeight("100%");
hbox.setHflex("1");
hbox.setPack("center");
Cell leftCell = new Cell();
hbox.appendChild(leftCell);
leftCell.setWidth("100%");
infoLine = new Label();
west = new Div();
west.setStyle("text-align: left; ");
west.appendChild(infoLine);
Vbox vbox = new Vbox();
vbox.setPack("center");
LayoutUtils.addSclass("status", vbox);
vbox.appendChild(west);
leftCell.appendChild(vbox);
this.appendChild(hbox);
}
/**
* Set Info Line
* @param text text
*/
public void setInfo (String text)
{
infoLine.setValue(text != null ? text : "");
infoLine.setTooltiptext(text);
infoLine.setStyle("font-weight: bold;");
} // setInfo
}

View File

@ -1,179 +0,0 @@
/******************************************************************************
* Copyright (C) 2008 Low Heng Sin *
* Copyright (C) 2009 Idalica Corporation *
* 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. *
*****************************************************************************/
package org.adempiere.webui.component;
import java.util.ArrayList;
import java.util.List;
import org.adempiere.webui.AdempiereIdGenerator;
import org.adempiere.webui.component.ADTabListModel.ADTabLabel;
import org.zkoss.zhtml.Button;
import org.zkoss.zhtml.Text;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
/**
*
* @author <a href="mailto:hengsin@gmail.com">Low Heng Sin</a>
*
*/
public class ADButtonTabList extends Panel implements IADTabList, EventListener {
/**
*
*/
private static final long serialVersionUID = -9203013067784673646L;
private List<ADTabLabel> listItems = new ArrayList<ADTabLabel>();
private List<EventListener> listeners = new ArrayList<EventListener>();
private IADTab tabbox;
private int selectedIndex = 0;
private int tabPlacement = IADTab.LEFT;
public ADButtonTabList() {
this.setStyle("margin:0;padding:0");
}
/**
* Set tab placement ( left or right )
* @param tabPlacement
*/
public void setTabplacement(int tabPlacement) {
if (tabPlacement != IADTab.LEFT && tabPlacement != IADTab.RIGHT)
return;
else if (tabPlacement == this.tabPlacement)
return;
else {
this.tabPlacement = tabPlacement;
this.invalidate();
}
}
public synchronized void refresh() {
List<?> childs = getChildren();
int childCount = childs.size();
for (int c = childCount - 1; c >=0; c--) {
removeChild((Component) childs.get(c));
}
Object[] items = listItems.toArray();
int tabWidth = 100;
List<Button> btnList = new ArrayList<Button>();
for (int i = 0; i < items.length; i++) {
ADTabLabel tabLabel = (ADTabLabel) items[i];
Button button = new Button();
button.setDynamicProperty("Title", tabLabel.description);
button.setAttribute(AdempiereIdGenerator.ZK_COMPONENT_PREFIX_ATTRIBUTE, "unqADButtonTab_" + tabLabel.windowNo + "_" + i);
Text text = new Text(tabLabel.label);
text.setAttribute("ad_tab_id", tabLabel.AD_Tab_ID);
button.appendChild(text);
int s = tabbox.getSelectedIndex();
if ( s == i) {
button.setSclass("adwindow-navbtn-sel " + (tabPlacement == IADTab.LEFT ? "adwindow-left-navbtn-sel" : "adwindow-right-navbtn-sel"));
button.setDynamicProperty("disabled", null);
} else {
if (!tabbox.canNavigateTo(s, i)) {
button.setDynamicProperty("disabled", "disabled");
button.setSclass("adwindow-navbtn-dis " + (tabPlacement == IADTab.LEFT ? "adwindow-left-navbtn-dis" : "adwindow-right-navbtn-dis"));
if (!tabbox.isDisplay(i))
button.setVisible(false);
else
button.setVisible(true);
} else {
button.setDynamicProperty("disabled", null);
button.setSclass("adwindow-navbtn-uns " + (tabPlacement == IADTab.LEFT ? "adwindow-left-navbtn-uns" : "adwindow-right-navbtn-uns"));
button.setVisible(true);
}
}
String style = (tabPlacement == IADTab.LEFT ? "margin-left:" : "margin-right:") + (tabLabel.tabLevel*15+5) + "px";
if (button.isVisible()) {
int width = tabLabel.label.length() * 10 + 20;
if (width > tabWidth)
tabWidth = width;
}
btnList.add(button);
button.setStyle(style);
button.setParent(this);
button.addEventListener(Events.ON_CLICK, this);
if (i == 0) {
button.setSclass(button.getSclass() + " " + "adwindow-navbtn-first");
}
}
//set width
if (tabWidth > 190)
tabWidth = 190;
for (int i = 0; i < items.length; i++) {
ADTabLabel tabLabel = (ADTabLabel) items[i];
Button button = btnList.get(i);
if (!button.isVisible())
continue;
String width = (tabWidth - tabLabel.tabLevel*15)+"px";
button.setStyle(button.getStyle() + "; display: block; width:" + width);
}
}
public int getSelectedIndex() {
return selectedIndex;
}
public void setSelectedIndex(int index) {
this.selectedIndex = index;
}
public synchronized void setItems(List<ADTabLabel> listItems) {
this.listItems = listItems;
refresh();
}
public void setADTab(IADTab adTab) {
this.tabbox = adTab;
}
public void addSelectionEventListener(EventListener listener) {
listeners.add(listener);
}
public boolean removeSelectionEventListener(EventListener listener) {
return listeners.remove(listener);
}
public void onEvent(Event event) throws Exception {
Event selectEvent = new Event(Events.ON_SELECT, this);
Button button = (Button) event.getTarget();
int i = 0;
for (ADTabLabel tabLabel : listItems) {
Text text = (Text) button.getFirstChild();
if (tabLabel.label.equals(text.getValue())) {
if (text.getAttribute("ad_tab_id") == null) {
break;
}
Integer tabId = (Integer) text.getAttribute("ad_tab_id");
if (tabLabel.AD_Tab_ID == tabId) {
break;
}
}
i++;
}
selectedIndex = i;
for (EventListener listener : listeners) {
listener.onEvent(selectEvent);
}
}
}

View File

@ -14,6 +14,7 @@ package org.adempiere.webui.component;
import java.util.List;
import org.adempiere.webui.adwindow.IADTabbox;
import org.zkoss.zul.AbstractListModel;
import org.zkoss.zul.Listbox;
import org.zkoss.zul.Listcell;
@ -28,9 +29,9 @@ public class ADTabListModel extends AbstractListModel implements ListitemRendere
*/
private static final long serialVersionUID = 7683969121090679214L;
List<ADTabLabel> listItems = null;
private IADTab tabbox;
private IADTabbox tabbox;
public ADTabListModel(List<ADTabLabel> listItems, IADTab tabbox) {
public ADTabListModel(List<ADTabLabel> listItems, IADTabbox tabbox) {
this.listItems = listItems;
this.tabbox = tabbox;
}

View File

@ -1,162 +0,0 @@
/******************************************************************************
* 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.ArrayList;
import java.util.List;
import org.adempiere.webui.LayoutUtils;
import org.adempiere.webui.panel.IADTabpanel;
import org.compiere.model.DataStatusEvent;
import org.compiere.model.GridTab;
import org.compiere.util.CLogger;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zul.Div;
/**
*
* @author <a href="mailto:agramdass@gmail.com">Ashley G Ramdass</a>
* @author <a href="mailto:hengsin@gmail.com">Low Heng Sin</a>
* @date Feb 25, 2007
* @version $Revision: 0.10 $
*/
public class CompositeADTab extends AbstractADTab
{
/** Logger */
@SuppressWarnings("unused")
private static CLogger log = CLogger.getCLogger (CompositeADTab.class);
private List<ADTabListModel.ADTabLabel> tabLabelList = new ArrayList<ADTabListModel.ADTabLabel>();
private Div div;
protected ADButtonTabList tabList;
public CompositeADTab()
{
tabList = new ADButtonTabList();
tabList.setADTab(this);
}
protected Component doCreatePart(Component parent)
{
div= new Div();
if (parent != null) {
div.setParent(parent);
LayoutUtils.addSclass("adtab-body", div);
} else {
div.setPage(page);
}
return div;
}
@Override
protected void doAddTab(GridTab gTab, IADTabpanel tabPanel) {
tabPanel.setParent(div);
tabPanel.setVisible(false);
ADTabListModel.ADTabLabel tabLabel = new ADTabListModel.ADTabLabel(gTab.getName(), gTab.getTabLevel(),gTab.getDescription(),
gTab.getWindowNo(),gTab.getAD_Tab_ID());
tabLabelList.add(tabLabel);
}
/**
* Evaluate Tab Logic
* @param e event
*/
public void evaluate (DataStatusEvent e)
{
tabList.setItems(tabLabelList);
super.evaluate(e);
} // evaluate
@Override
protected void updateTabState() {
tabList.refresh();
}
/**
* Return the selected Tab Panel
*/
public IADTabpanel getSelectedTabpanel()
{
for(int i = 0; i < tabPanelList.size(); i++) {
if (tabPanelList.get(i).isVisible())
return tabPanelList.get(i);
}
return null;
}
public int getSelectedIndex() {
for(int i = 0; i < tabPanelList.size(); i++) {
if (tabPanelList.get(i).isVisible())
return i;
}
return -1;
}
public void addSelectionEventListener(EventListener listener) {
tabList.addSelectionEventListener(listener);
}
public Component getTabSelectionComponent() {
return tabList;
}
@Override
protected void doTabSelectionChanged(int oldIndex, int newIndex) {
IADTabpanel oldTabpanel = oldIndex >= 0 ? tabPanelList.get(oldIndex) : null;
IADTabpanel newTabpanel = tabPanelList.get(newIndex);
if (oldTabpanel != null) {
oldTabpanel.setVisible(false);
}
newTabpanel.createUI();
newTabpanel.setVisible(true);
if (tabList.getSelectedIndex() != newIndex)
tabList.setSelectedIndex(newIndex);
}
public boolean isUseExternalSelection() {
return true;
}
public Component getComponent() {
return div;
}
/**
* @param tabPlacement
*/
public void setTabplacement(int tabPlacement) {
tabList.setTabplacement(tabPlacement);
}
@Override
public IADTabpanel findADTabpanel(GridTab gTab) {
for (IADTabpanel tabpanel : tabPanelList) {
if (tabpanel.getGridTab() == gTab) {
return tabpanel;
}
}
return null;
}
}

View File

@ -1,418 +0,0 @@
/******************************************************************************
* Copyright (C) 2008 Low Heng Sin *
* 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. *
*****************************************************************************/
package org.adempiere.webui.component;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.adempiere.webui.component.ListPanel;
import org.adempiere.webui.editor.WButtonEditor;
import org.adempiere.webui.editor.WEditor;
import org.adempiere.webui.editor.WEditorPopupMenu;
import org.adempiere.webui.editor.WebEditorFactory;
import org.adempiere.webui.event.ContextMenuListener;
import org.adempiere.webui.panel.AbstractADWindowPanel;
import org.adempiere.webui.session.SessionManager;
import org.adempiere.webui.util.GridTabDataBinder;
import org.adempiere.webui.window.ADWindow;
import org.compiere.model.GridField;
import org.compiere.model.GridTab;
import org.compiere.util.DisplayType;
import org.compiere.util.NamePair;
import org.zkoss.zk.ui.Component;
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.Image;
import org.zkoss.zul.Listbox;
import org.zkoss.zul.Listcell;
import org.zkoss.zul.Listitem;
import org.zkoss.zul.ListitemRenderer;
import org.zkoss.zul.ListitemRendererExt;
import org.zkoss.zul.Paging;
import org.zkoss.zul.RendererCtrl;
/**
* ListItem renderer for GridTab list box.
* @author hengsin
*
*/
public class GridTabListItemRenderer implements ListitemRenderer, ListitemRendererExt, RendererCtrl {
private static final int MAX_TEXT_LENGTH = 60;
private GridTab gridTab;
private int windowNo;
private GridTabDataBinder dataBinder;
private Map<GridField, WEditor> editors = new HashMap<GridField, WEditor>();
private Paging paging;
private ListPanel listPanel;
/**
*
* @param gridTab
* @param windowNo
*/
public GridTabListItemRenderer(GridTab gridTab, int windowNo) {
this.gridTab = gridTab;
this.windowNo = windowNo;
this.dataBinder = new GridTabDataBinder(gridTab);
}
/**
* @param listitem
* @param data
* @see ListitemRenderer#render(Listitem, Object)
*/
@Override
public void render(Listitem listitem, Object data, int index) throws Exception {
//don't render if not visible
if (listPanel != null && !listPanel.isVisible()) {
return;
}
GridField[] listPanelFields = listPanel.getFields();
int columnCount = listPanelFields.length;
GridField[] gridTabFields = gridTab.getFields();
boolean isGridViewCustomized = gridTabFields.length != listPanelFields.length;
if (!isGridViewCustomized) {
for(int i = 0; i < gridTabFields.length; i++) {
if (listPanelFields[i].getAD_Field_ID() != gridTabFields[i].getAD_Field_ID()) {
isGridViewCustomized = true;
break;
}
}
}
for(Component c = listitem.getParent(); c != null; c = c.getParent()) {
if (!c.isVisible())
return;
}
Object[] values = null;
if (!isGridViewCustomized) {
values = (Object[])data;
} else {
List<Object> dataList = new ArrayList<Object>();
for(GridField gridField : listPanelFields) {
for(int i = 0; i < gridTabFields.length; i++) {
if (gridField.getAD_Field_ID() == gridTabFields[i].getAD_Field_ID()) {
dataList.add(((Object[])data)[i]);
break;
}
}
}
values = dataList.toArray(new Object[0]);
}
for (int i = 0; i < columnCount; i++) {
if (!listPanelFields[i].isDisplayedGrid()) {
continue;
}
if (editors.get(listPanelFields[i]) == null)
editors.put(listPanelFields[i], WebEditorFactory.getEditor(listPanelFields[i], true));
int rowIndex = listitem.getIndex();
if (paging != null && paging.getPageSize() > 0) {
rowIndex = (paging.getActivePage() * paging.getPageSize()) + rowIndex;
}
Listcell cell = null;
if (rowIndex == gridTab.getCurrentRow() && listPanelFields[i].isEditable(true)) {
cell = getEditorCell(listPanelFields[i], values[i], i);
cell.setParent(listitem);
} else {
if (listPanelFields[i].getDisplayType() == DisplayType.YesNo) {
cell = new Listcell("", null);
cell.setParent(listitem);
cell.setStyle("text-align:center");
createReadonlyCheckbox(values[i], cell);
} else {
String text = getDisplayText(values[i], i);
String display = text;
if (text != null && text.length() > MAX_TEXT_LENGTH)
display = text.substring(0, MAX_TEXT_LENGTH - 3) + "...";
cell = new Listcell(display, null);
cell.setParent(listitem);
if (text != null && text.length() > MAX_TEXT_LENGTH)
cell.setTooltiptext(text);
if (DisplayType.isNumeric(listPanelFields[i].getDisplayType())) {
cell.setStyle("text-align:right");
} else if (listPanelFields[i].getDisplayType() == DisplayType.Image) {
cell.setStyle("text-align:center");
}
}
}
CellListener listener = new CellListener((Listbox) listitem.getParent());
cell.addEventListener(Events.ON_DOUBLE_CLICK, listener);
}
}
private void createReadonlyCheckbox(Object value, Listcell cell) {
Checkbox checkBox = new Checkbox();
if (value != null && "true".equalsIgnoreCase(value.toString()))
checkBox.setChecked(true);
else
checkBox.setChecked(false);
checkBox.setDisabled(true);
checkBox.setParent(cell);
}
private Listcell getEditorCell(GridField gridField, Object object, int i) {
Listcell cell = new Listcell("", null);
WEditor editor = editors.get(gridField);
if (editor != null) {
if (editor instanceof WButtonEditor)
{
Object window = SessionManager.getAppDesktop().findWindow(windowNo);
if (window != null && window instanceof ADWindow)
{
AbstractADWindowPanel windowPanel = ((ADWindow)window).getADWindowPanel();
((WButtonEditor)editor).addActionListener(windowPanel);
}
}
else
{
editor.addValueChangeListener(dataBinder);
}
cell.appendChild(editor.getComponent());
if (editor.getComponent() instanceof Checkbox || editor.getComponent() instanceof Image) {
cell.setStyle("text-align:center");
}
else if (DisplayType.isNumeric(gridField.getDisplayType())) {
cell.setStyle("text-align:right");
}
gridField.addPropertyChangeListener(editor);
editor.setValue(gridField.getValue());
WEditorPopupMenu popupMenu = editor.getPopupMenu();
if (popupMenu != null)
{
popupMenu.addMenuListener((ContextMenuListener)editor);
cell.appendChild(popupMenu);
}
//streach component to fill grid cell
editor.fillHorizontal();
}
return cell;
}
/**
* Detach all editor and optionally set the current value of the editor as cell label.
* @param updateCellLabel
*/
public void stopEditing(boolean updateCellLabel) {
for (Entry<GridField, WEditor> entry : editors.entrySet()) {
if (entry.getValue().getComponent().getParent() != null) {
if (updateCellLabel) {
Listcell cell = (Listcell) entry.getValue().getComponent().getParent();
if (entry.getKey().getDisplayType() == DisplayType.YesNo) {
cell.setLabel("");
createReadonlyCheckbox(entry.getValue().getValue(), cell);
} else {
cell.setLabel(getDisplayText(entry.getValue().getValue(), getColumnIndex(entry.getKey())));
}
}
entry.getValue().getComponent().detach();
entry.getKey().removePropertyChangeListener(entry.getValue());
entry.getValue().removeValuechangeListener(dataBinder);
}
}
}
private int getColumnIndex(GridField field) {
GridField[] fields = listPanel.getFields();
for(int i = 0; i < fields.length; i++) {
if (fields[i] == field)
return i;
}
return 0;
}
/**
* @see ListitemRendererExt#getControls()
*/
public int getControls() {
return DETACH_ON_RENDER;
}
/**
* @param item
* @see ListitemRendererExt#newListcell(Listitem)
*/
public Listcell newListcell(Listitem item) {
ListCell listCell = new ListCell();
listCell.applyProperties();
listCell.setParent(item);
return listCell;
}
/**
* @param listbox
* @see ListitemRendererExt#newListitem(Listbox)
*/
public Listitem newListitem(Listbox listbox) {
ListItem item = new ListItem();
item.applyProperties();
return item;
}
private Map<Integer, Map<Object, String>> lookupCache = null;
private String getDisplayText(Object value, int columnIndex)
{
if (value == null)
return "";
GridField[] gridField = listPanel.getFields();
if (gridField[columnIndex].isEncryptedField())
{
return "********";
}
else if (gridField[columnIndex].isLookup())
{
if (value == null) return "";
if (lookupCache != null)
{
Map<Object, String> cache = lookupCache.get(columnIndex);
if (cache != null && cache.size() >0)
{
String text = cache.get(value);
if (text != null)
{
return text;
}
}
}
NamePair namepair = gridField[columnIndex].getLookup().get(value);
if (namepair != null)
{
String text = namepair.getName();
if (lookupCache != null)
{
Map<Object, String> cache = lookupCache.get(columnIndex);
if (cache == null)
{
cache = new HashMap<Object, String>();
lookupCache.put(columnIndex, cache);
}
cache.put(value, text);
}
return text;
}
else
return "";
}
else if (DisplayType.getClass(gridField[columnIndex].getDisplayType(), false).equals(Timestamp.class))
{
SimpleDateFormat dateFormat = DisplayType.getDateFormat(DisplayType.Date);
return dateFormat.format((Timestamp)value);
}
else if (DisplayType.isNumeric(gridField[columnIndex].getDisplayType()))
{
return DisplayType.getNumberFormat(gridField[columnIndex].getDisplayType()).format(value);
}
else if (DisplayType.Button == gridField[columnIndex].getDisplayType())
{
return "";
}
else if (DisplayType.Image == gridField[columnIndex].getDisplayType())
{
if (value == null || (Integer)value <= 0)
return "";
else
return "...";
}
else
return value.toString();
}
class CellListener implements EventListener {
private Listbox _listbox;
public CellListener(Listbox listbox) {
_listbox = listbox;
}
public void onEvent(Event event) throws Exception {
if (Events.ON_DOUBLE_CLICK.equals(event.getName())) {
Event evt = new Event(Events.ON_DOUBLE_CLICK, _listbox);
Events.sendEvent(_listbox, evt);
}
}
}
/**
* Is renderer initialize
* @return boolean
*/
public boolean isInitialize() {
return !editors.isEmpty();
}
/**
*
* @return active editor list
*/
public List<WEditor> getEditors() {
List<WEditor> editorList = new ArrayList<WEditor>();
if (!editors.isEmpty())
editorList.addAll(editors.values());
return editorList;
}
/**
* @param paging
*/
public void setPaging(Paging paging) {
this.paging = paging;
}
/**
* @see RendererCtrl#doCatch(Throwable)
*/
public void doCatch(Throwable ex) throws Throwable {
lookupCache = null;
}
/**
* @see RendererCtrl#doFinally()
*/
public void doFinally() {
lookupCache = null;
}
/**
* @see RendererCtrl#doTry()
*/
public void doTry() {
lookupCache = new HashMap<Integer, Map<Object,String>>();
}
public void setListPanel(ListPanel listPanel) {
this.listPanel = listPanel;
}
public ListPanel getListPanel() {
return listPanel;
}
}

View File

@ -1,16 +0,0 @@
package org.adempiere.webui.component;
/**
*
* @author <a href="mailto:hengsin@gmail.com">Low Heng Sin</a>
*
*/
public interface IADTabList {
int getSelectedIndex();
void setSelectedIndex(int curTabIndex);
void refresh();
}

View File

@ -1,484 +0,0 @@
/******************************************************************************
* Copyright (C) 2008 Low Heng Sin *
* 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. *
*****************************************************************************/
package org.adempiere.webui.component;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.table.AbstractTableModel;
import org.adempiere.model.MTabCustomization;
import org.adempiere.webui.LayoutUtils;
import org.adempiere.webui.editor.WEditor;
import org.compiere.model.GridField;
import org.compiere.model.GridTab;
import org.compiere.model.GridTable;
import org.compiere.model.MSysConfig;
import org.compiere.util.DisplayType;
import org.compiere.util.Env;
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.Borderlayout;
import org.zkoss.zul.Center;
import org.zkoss.zul.South;
import org.zkoss.zul.Paging;
import org.zkoss.zul.event.ZulEvents;
/**
* Grid view implemented using the Listbox component
* @author Low Heng Sin
*
*/
public class ListPanel extends Borderlayout implements EventListener
{
/**
*
*/
private static final long serialVersionUID = 4145737989132101461L;
private static final int MIN_COLUMN_WIDTH = 100;
private static final int MAX_COLUMN_WIDTH = 300;
private Listbox listbox = null;
private int pageSize = 100;
private GridField[] gridField;
private AbstractTableModel tableModel;
private int numColumns = 5;
private int windowNo;
private GridTab gridTab;
private boolean init;
private GridTableListModel listModel;
private Paging paging;
private GridTabListItemRenderer renderer;
private South south;
private Map<Integer, String> columnWidthMap;
public ListPanel()
{
this(0);
}
/**
* @param windowNo
*/
public ListPanel(int windowNo)
{
this.windowNo = windowNo;
listbox = new Listbox();
south = new South();
this.appendChild(south);
//default paging size
pageSize = MSysConfig.getIntValue(MSysConfig.ZK_PAGING_SIZE, 100);
}
/**
*
* @param gridTab
*/
public void init(GridTab gridTab)
{
if (init) return;
setupFields(gridTab);
setupColumns();
render();
updateListIndex(true);
this.init = true;
}
private void setupFields(GridTab gridTab) {
this.gridTab = gridTab;
tableModel = gridTab.getTableModel();
GridField[] tmpFields = ((GridTable)tableModel).getFields();
MTabCustomization tabCustomization = MTabCustomization.get(Env.getCtx(), Env.getAD_User_ID(Env.getCtx()), gridTab.getAD_Tab_ID(), null);
if (tabCustomization != null && tabCustomization.getAD_Tab_Customization_ID() > 0
&& tabCustomization.getCustom() != null && tabCustomization.getCustom().trim().length() > 0) {
String custom = tabCustomization.getCustom().trim();
String[] customComponent = custom.split(";");
String[] fieldIds = customComponent[0].split("[,]");
List<GridField> fieldList = new ArrayList<GridField>();
for(String fieldIdStr : fieldIds) {
fieldIdStr = fieldIdStr.trim();
if (fieldIdStr.length() == 0) continue;
int AD_Field_ID = Integer.parseInt(fieldIdStr);
for(GridField gridField : tmpFields) {
if (gridField.getAD_Field_ID() == AD_Field_ID) {
fieldList.add(gridField);
break;
}
}
}
gridField = fieldList.toArray(new GridField[0]);
if (customComponent.length == 2) {
String[] widths = customComponent[1].split("[,]");
for(int i = 0; i< gridField.length; i++) {
columnWidthMap.put(gridField[i].getAD_Field_ID(), widths[i]);
}
}
} else {
gridField = tmpFields;
}
numColumns = gridField.length;
}
/**
*
* @return boolean
*/
public boolean isInit() {
return init;
}
/**
*
* @param gridTab
*/
public void activate(GridTab gridTab) {
if (isInit())
{
if (this.gridTab != gridTab)
{
init = false;
init(gridTab);
}
else
{
if (renderer != null)
renderer.stopEditing(false);
int oldSelected = listbox.getSelectedIndex();
updateListIndex(false);
if (listbox.getSelectedIndex() == oldSelected && oldSelected >= 0)
listModel.updateComponent(oldSelected);
}
}
else
init(gridTab);
}
/**
*
* @param gridTab
*/
public void refresh(GridTab gridTab) {
if (this.gridTab != gridTab)
{
init = false;
init(gridTab);
}
else
{
renderer.stopEditing(false);
listbox.setModel(listModel);
updateListIndex(true);
}
}
/**
* Update listbox selection to sync with grid current row pointer changes
*/
public void updateListIndex() {
updateListIndex(false);
}
/**
* Update listbox selection to sync with grid current row pointer changes
* @param updateSelectionOnly if true, doesn't attempt to refresh current row from model
*/
public void updateListIndex(boolean updateSelectionOnly) {
int rowIndex = gridTab.isOpen() ? gridTab.getCurrentRow() : -1;
if (pageSize > 0) {
if (paging.getTotalSize() != gridTab.getRowCount())
paging.setTotalSize(gridTab.getRowCount());
int pgIndex = rowIndex % pageSize;
int pgNo = (rowIndex - pgIndex) / pageSize;
boolean pgChange = false;
if (listModel.getPage() != pgNo) {
listModel.setPage(pgNo);
pgChange = true;
}
if (paging.getActivePage() != pgNo) {
paging.setActivePage(pgNo);
}
if (listbox.getSelectedIndex() != pgIndex) {
if (!updateSelectionOnly) {
renderer.stopEditing(false);
if (!pgChange) {
listModel.updateComponent(listbox.getSelectedIndex());
}
listModel.updateComponent(pgIndex);
}
listbox.setSelectedIndex(pgIndex);
}
} else {
if (listbox.getSelectedIndex() != rowIndex) {
if (!updateSelectionOnly) {
renderer.stopEditing(false);
listModel.updateComponent(listbox.getSelectedIndex());
listModel.updateComponent(rowIndex);
}
listbox.setSelectedIndex(rowIndex);
}
}
}
/**
* Set paging size
* @param pageSize
*/
public void setPageSize(int pageSize)
{
this.pageSize = pageSize;
}
public void clear()
{
this.getChildren().clear();
}
/**
*
* @param bool
*/
public void showGrid(boolean bool)
{
if (bool)
this.setVisible(true);
else
this.setVisible(false);
}
private void setupColumns()
{
if (init) return;
ListHead header = new ListHead();
header.setSizable(true);
Map<Integer, String> colnames = new HashMap<Integer, String>();
int index = 0;
for (int i = 0; i < numColumns; i++)
{
if (gridField[i].isDisplayed())
{
colnames.put(index, gridField[i].getHeader());
index++;
ListHeader colHeader = new ListHeader();
colHeader.setSort("auto");
colHeader.setLabel(gridField[i].getHeader());
if (columnWidthMap != null && columnWidthMap.get(gridField[i].getAD_Field_ID()) != null) {
colHeader.setWidth(columnWidthMap.get(gridField[i].getAD_Field_ID()));
} else {
int l = DisplayType.isNumeric(gridField[i].getDisplayType())
? 100 : gridField[i].getDisplayLength() * 9;
if (gridField[i].getHeader().length() * 9 > l)
l = gridField[i].getHeader().length() * 9;
if (l > MAX_COLUMN_WIDTH)
l = MAX_COLUMN_WIDTH;
else if ( l < MIN_COLUMN_WIDTH)
l = MIN_COLUMN_WIDTH;
colHeader.setWidth(Integer.toString(l) + "px");
}
header.appendChild(colHeader);
}
}
listbox.appendChild(header);
}
private void render()
{
LayoutUtils.addSclass("adtab-grid-panel", this);
listbox.setVflex(true);
listbox.setFixedLayout(true);
listbox.addEventListener(Events.ON_SELECT, this);
LayoutUtils.addSclass("adtab-grid", listbox);
updateModel();
Center center = new Center();
center.appendChild(listbox);
this.appendChild(center);
if (pageSize > 0)
{
paging = new Paging();
paging.setPageSize(pageSize);
paging.setTotalSize(tableModel.getRowCount());
paging.setDetailed(true);
south.appendChild(paging);
paging.addEventListener(ZulEvents.ON_PAGING, this);
renderer.setPaging(paging);
this.getParent().invalidate();
}
else
{
south.setVisible(false);
}
}
private void updateModel() {
listModel = new GridTableListModel((GridTable)tableModel, windowNo);
listModel.setPageSize(pageSize);
if (renderer != null)
renderer.stopEditing(false);
renderer = new GridTabListItemRenderer(gridTab, windowNo);
listbox.setItemRenderer(renderer);
listbox.setModel(listModel);
}
/**
* deactive panel
*/
public void deactivate() {
if (renderer != null)
renderer.stopEditing(false);
}
public void onEvent(Event event) throws Exception
{
if (event == null)
return;
else if (event.getTarget() == listbox)
{
int index = listbox.getSelectedIndex();
onSelectedRowChange(index);
}
else if (event.getTarget() == paging)
{
int pgNo = paging.getActivePage();
if (pgNo != listModel.getPage())
{
listbox.clearSelection();
listModel.setPage(pgNo);
listbox.setSelectedIndex(0);
onSelectedRowChange(0);
}
}
}
private void onSelectedRowChange(int index) {
if (updateModelIndex()) {
listModel.updateComponent(index);
listbox.setSelectedIndex(index);
} else if (!renderer.isInitialize()) {
listModel.updateComponent(index);
listbox.setSelectedIndex(index);
}
}
private boolean updateModelIndex() {
int rowIndex = listbox.getSelectedIndex();
if (pageSize > 0) {
int start = listModel.getPage() * listModel.getPageSize();
rowIndex = start + rowIndex;
}
if (gridTab.getCurrentRow() != rowIndex) {
renderer.stopEditing(true);
gridTab.navigate(rowIndex);
return true;
}
return false;
}
/**
*
* @return Listbox
*/
public Listbox getListbox() {
return listbox;
}
/**
* validate the display properties of fields of current row
* @param col
*/
public void dynamicDisplay(int col) {
if (!gridTab.isOpen())
{
return;
}
// Selective
if (col > 0)
return;
boolean noData = gridTab.getRowCount() == 0;
List<WEditor> list = renderer.getEditors();
for (WEditor comp : list)
{
GridField mField = comp.getGridField();
if (mField != null && mField.getIncluded_Tab_ID() <= 0)
{
if (noData)
{
comp.setReadWrite(false);
}
else
{
comp.dynamicDisplay();
boolean rw = mField.isEditable(true); // r/w - check Context
comp.setReadWrite(rw);
}
}
} // all components
}
/**
*
* @param windowNo
*/
public void setWindowNo(int windowNo) {
this.windowNo = windowNo;
}
public void reInit() {
this.setupFields(gridTab);
if (listbox.getListHead() != null) {
listbox.removeChild(listbox.getListHead());
}
init = false;
setupColumns();
init = true;
updateModel();
}
public GridField[] getFields() {
return gridField;
}
}

View File

@ -24,15 +24,13 @@ import java.text.ParseException;
import org.adempiere.webui.LayoutUtils;
import org.compiere.util.DisplayType;
import org.compiere.util.Env;
import org.zkoss.zhtml.Table;
import org.zkoss.zhtml.Td;
import org.zkoss.zhtml.Tr;
import org.zkoss.zk.ui.Page;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zul.Decimalbox;
import org.zkoss.zul.Div;
import org.zkoss.zul.Hbox;
import org.zkoss.zul.Hlayout;
import org.zkoss.zul.Popup;
import org.zkoss.zul.Vbox;
@ -75,35 +73,23 @@ public class NumberBox extends Div
private void init()
{
Table grid = new Table();
appendChild(grid);
grid.setStyle("border: none; padding: 0px; margin: 0px;");
grid.setDynamicProperty("border", "0");
grid.setDynamicProperty("cellpadding", "0");
grid.setDynamicProperty("cellspacing", "0");
Tr tr = new Tr();
grid.appendChild(tr);
tr.setStyle("border: none; padding: 0px; margin: 0px; white-space:nowrap; ");
Hlayout hlayout = new Hlayout();
hlayout.setHflex("1");
appendChild(hlayout);
Td td = new Td();
tr.appendChild(td);
td.setStyle("border: none; padding: 0px; margin: 0px;");
decimalBox = new Decimalbox();
if (integral)
decimalBox.setScale(0);
decimalBox.setStyle("display: inline;text-align:right");
td.appendChild(decimalBox);
decimalBox.setHflex("1");
hlayout.appendChild(decimalBox);
Td btnColumn = new Td();
tr.appendChild(btnColumn);
btnColumn.setStyle("border: none; padding: 0px; margin: 0px;");
btnColumn.setSclass("editor-button");
btn = new Button();
btn.setImage("/images/Calculator10.png");
btn.setTabindex(-1);
btn.setHflex("min");
LayoutUtils.addSclass("editor-button", btn);
btnColumn.appendChild(btn);
hlayout.appendChild(btn);
popup = getCalculatorPopup();
appendChild(popup);

View File

@ -37,6 +37,7 @@ import org.compiere.util.DisplayType;
import org.compiere.util.Env;
import org.compiere.util.Msg;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.HtmlBasedComponent;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
@ -315,11 +316,20 @@ public abstract class WEditor implements EventListener<Event>, PropertyChangeLis
/**
* @param evt
*/
public void propertyChange(PropertyChangeEvent evt)
public void propertyChange(final PropertyChangeEvent evt)
{
if (evt.getPropertyName().equals(org.compiere.model.GridField.PROPERTY))
{
setValue((evt.getNewValue()));
if (Executions.getCurrent() == null) {
Executions.schedule(this.getComponent().getDesktop(), new EventListener<Event>() {
@Override
public void onEvent(Event event) throws Exception {
setValue((evt.getNewValue()));
}
}, new Event("onPropertyChange"));
} else {
setValue((evt.getNewValue()));
}
}
}

View File

@ -55,20 +55,32 @@ public class WNumberEditor extends WEditor implements ContextMenuListener
private int displayType;
private boolean tableEditor;
public WNumberEditor()
{
this("Number", false, false, true, DisplayType.Number, "");
}
/**
*
* @param gridField
*/
public WNumberEditor(GridField gridField)
{
this(false, gridField);
}
/**
*
* @param gridField
*/
public WNumberEditor(GridField gridField)
public WNumberEditor(boolean tableEditor, GridField gridField)
{
super(new NumberBox(gridField.getDisplayType() == DisplayType.Integer),
gridField);
this.displayType = gridField.getDisplayType();
this.tableEditor = tableEditor;
init();
}
@ -112,7 +124,10 @@ public class WNumberEditor extends WEditor implements ContextMenuListener
displayLength = MAX_DISPLAY_LENGTH;
else if (displayLength <= 0 || displayLength < MIN_DISPLAY_LENGTH)
displayLength = MIN_DISPLAY_LENGTH;
getComponent().getDecimalbox().setCols(displayLength);
if (!tableEditor)
getComponent().getDecimalbox().setCols(displayLength);
// else
// getComponent().getDecimalbox().setCols(0);
}
if (DisplayType.isID(displayType))

View File

@ -34,4 +34,9 @@ public class WPasswordEditor extends WStringEditor
super.setTypePassword(true);
}
public WPasswordEditor(GridField gridField, boolean tableEditor)
{
super(gridField, tableEditor);
super.setTypePassword(true);
}
}

View File

@ -114,7 +114,8 @@ public class WStringEditor extends WEditor implements ContextMenuListener
{
displayLength = MAX_DISPLAY_LENGTH;
}
getComponent().setCols(displayLength);
if (!tableEditor)
getComponent().setCols(displayLength);
if (gridField.getDisplayType() == DisplayType.Text)
{
getComponent().setMultiline(true);

View File

@ -70,7 +70,7 @@ public class DefaultEditorFactory implements IEditorFactory {
{
if (gridField.isEncryptedField())
{
editor = new WPasswordEditor(gridField);
editor = new WPasswordEditor(gridField, tableEditor);
}
else
{
@ -90,7 +90,7 @@ public class DefaultEditorFactory implements IEditorFactory {
/** Number */
else if (DisplayType.isNumeric(displayType))
{
editor = new WNumberEditor(gridField);
editor = new WNumberEditor(tableEditor, gridField);
}
/** YesNo */
@ -104,7 +104,7 @@ public class DefaultEditorFactory implements IEditorFactory {
/** Text */
else if (displayType == DisplayType.Text || displayType == DisplayType.Memo || displayType == DisplayType.TextLong)
{
editor = new WStringEditor(gridField);
editor = new WStringEditor(gridField, tableEditor);
}
/** Date */

Binary file not shown.

After

Width:  |  Height:  |  Size: 603 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 814 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 835 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -8,6 +8,7 @@ html,body {
width: 100%;
background-color: #D4E3F4;
color: #333;
font-family: Helvetica,Arial,sans-serif;
overflow: hidden;
}
@ -174,15 +175,6 @@ html,body {
border-color: transparent;
}
.embedded-toolbar-button .z-toolbarbutton-body .z-toolbarbutton-cnt img {
width: 16px;
height: 16px;
padding: 0px 1px 0px 1px;
border-style: solid;
border-width: 1px;
border-color: transparent;
}
.depressed img {
border-width: 1px;
border-color: #9CBDFF;
@ -355,7 +347,7 @@ div.wc-modal, div.wc-modal-none, div.wc-highlighted, div.wc-highlighted-none {
}
.adwindow-status {
background-color: #D2E0EB;
background-color: #EEEEEE;
height: 20px;
}
@ -478,6 +470,12 @@ div.wc-modal, div.wc-modal-none, div.wc-highlighted, div.wc-highlighted-none {
-webkit-border-bottom-right-radius: 5px;
}
.adwindow-breadcrumb {
height: 30px;
background-color: transparent;
padding-left: 2px;
}
<%-- ad tab --%>
.adtab-body {
position: absolute;
@ -492,18 +490,14 @@ div.wc-modal, div.wc-modal-none, div.wc-highlighted, div.wc-highlighted-none {
margin: 0;
padding: 0;
border: none;
overflow: auto;
width: 100%;
height: 100%;
position: absolute;
position: relative;
}
.adtab-form {
width:100%;
height:100%;
border:none !important;
margin:0;
padding:0;
overflow-y: visible;
}
.adtab-form .z-grid {
@ -541,7 +535,6 @@ div.wc-modal, div.wc-modal-none, div.wc-highlighted, div.wc-highlighted-none {
}
.adtab-tabpanels {
width: 80%;
border-top: 1px solid #9CBDFF;
border-bottom: 1px solid #9CBDFF;
border-left: 2px solid #9CBDFF;
@ -789,6 +782,7 @@ img.z-group-img-close {
.z-tab-seld .z-tab-text, .z-tab .z-tab-text, div.z-treefooter-cnt, div.z-treecell-cnt, div.z-treecol-cnt,
.z-label, .z-toolbarbutton-cnt, tr.z-treerow, tr.z-treerow a, tr.z-treerow a:visited {
color: #333;
font-family: Helvetica,Arial,sans-serif;
}
.z-textbox-readonly, .z-intbox-readonly, .z-longbox-readonly, .z-doublebox-readonly, .z-decimalbox-readonly {
@ -924,3 +918,16 @@ div.simileAjax-bubble-container {
position: relative;
float: right;
}
tbody.z-grid-empty-body td {
text-align: left;
}
.adtab-detail-toolbar .z-toolbar-body {
width: 100%;
}
.z-notification .z-notification-cl,
.z-notification .z-notification-cnt {
width: 300px;
}