IDEMPIERE-5694 Listbox item and group rendering API enhancements (#1804)

* IDEMPIERE-5694 Listbox item and group rendering API enhancements

* IDEMPIERE-5694 Listbox item and group rendering API enhancements

- Fix css and rendering bugs
This commit is contained in:
hengsin 2023-04-28 17:14:28 +08:00 committed by GitHub
parent 254dcb3955
commit fdbbf093fb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 482 additions and 2 deletions

View File

@ -102,6 +102,7 @@ Export-Package: fi.jawsy.jawwa.zk.atmosphere,
org.adempiere.webui.factory,
org.adempiere.webui.grid,
org.adempiere.webui.info,
org.adempiere.webui.listbox.renderer,
org.adempiere.webui.panel,
org.adempiere.webui.panel.action,
org.adempiere.webui.part,
@ -185,9 +186,9 @@ Export-Package: fi.jawsy.jawwa.zk.atmosphere,
web.js.ckez.ext.CKeditor.plugins.widget.images,
web.js.ckez.ext.CKeditor.skins,
web.js.ckez.ext.CKeditor.vendor,
web.js.dragdrop.attachment,
web.js.html2canvas,
web.js.jawwa.atmosphere,
web.js.dragdrop.attachment,
web.js.jquery.maskedinput,
web.js.org.idempiere.commons,
web.js.org.idempiere.websocket,

View File

@ -57,6 +57,6 @@ Copyright (C) 2007 Ashley G Ramdass (ADempiere WebUI).
<!-- this js module doesn't actually exists and it is here for default theme version -->
<!-- since loading of js module is on demand, it doesn't cause any error as long as you don't try to load it -->
<javascript-module name="idempiere.theme.default" version="202304141300" />
<javascript-module name="idempiere.theme.default" version="202304260800" />
</language>

View File

@ -0,0 +1,231 @@
/***********************************************************************
* This file is part of iDempiere ERP Open Source *
* http://www.idempiere.org *
* *
* Copyright (C) Contributors *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* 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., 51 Franklin Street, Fifth Floor, Boston, *
* MA 02110-1301, USA. *
* *
* Contributors: *
* - hengsin *
**********************************************************************/
package org.adempiere.webui.component;
import java.util.ArrayList;
import java.util.List;
import org.adempiere.webui.util.ZKUpdateUtil;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.UiException;
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.Label;
import org.zkoss.zul.Listbox;
import org.zkoss.zul.Listcell;
import org.zkoss.zul.Listgroup;
import org.zkoss.zul.Listitem;
import org.zkoss.zul.Span;
/**
* Single level grouping for {@link Listbox}.<br/>
* Note that due to a class hierarchy issue, this wouldn't works with {@link org.adempiere.webui.component.Listbox}.
*/
public class ListitemGroup extends Listgroup {
/**
* generated serial id
*/
private static final long serialVersionUID = -1790997329703776505L;
/** Listitem attribute to store visibility of a group */
public static final String GROUP_LISTITEM_VISIBLE_KEY = "groupListitemVisible";
/** The list of Listitem of this group */
private List<Listitem> m_items = new ArrayList<Listitem>();
/**
* Default constructor
*/
public ListitemGroup() {
super();
}
/**
* @param label group label
*/
public ListitemGroup(String label) {
super(label);
}
/**
* @param <T>
* @param label
* @param value
*/
public <T> ListitemGroup(String label, T value) {
super(label, value);
}
/**
* @return group label/header
*/
public String getLabel() {
final Component cell = getFirstChild();
return cell != null && cell instanceof ListitemGroupHeader ? ((ListitemGroupHeader)cell).getTitle() : null;
}
@Override
public void setLabel(String label) {
getOrCreateGroupHeader().setTitle(label);
}
/**
* Set column span of group header (first cell)
* @param colspan
*/
public void setColspan(int colspan) {
getOrCreateGroupHeader().setSpan(colspan);
}
/**
* Get/create group header cell
* @return {@link ListitemGroupHeader}
*/
private ListitemGroupHeader getOrCreateGroupHeader() {
Component cell = getChildren().size() == 0 || getChildren().size() == 1 ? getFirstChild() : getFirstChild().getNextSibling();
if (cell == null || cell instanceof ListitemGroupHeader) {
if (cell == null) cell = new ListitemGroupHeader();
cell.applyProperties();
cell.setParent(this);
return (ListitemGroupHeader)cell;
}
throw new UiException("Unsupported child for setLabel: "+cell);
}
@Override
public void setOpen(boolean open) {
super.setOpen(open);
getOrCreateGroupHeader().setOpen(isOpen());
if (getParent() != null)
{
for (Listitem item : m_items)
{
boolean visible = true;
String value = (String) item.getAttribute(GROUP_LISTITEM_VISIBLE_KEY);
if (value != null)
visible = value.equals("true");
item.setVisible(isOpen() && visible); // hide the row of the children when group is not open
}
}
}
/**
* Add Listitem to group
* @param item
*/
public void add(Listitem item) {
m_items.add(item);
}
/**
* Custom Listcell class for list group header
*/
public static class ListitemGroupHeader extends Listcell implements EventListener<Event>
{
/**
* generated serial id
*/
private static final long serialVersionUID = -4070011056533999557L;
private Span span;
private Label lbl;
private String title;
private boolean open;
/**
* Default constructor
*/
public ListitemGroupHeader()
{
super();
init();
setTitle(null);
setOpen(true);
ZKUpdateUtil.setVflex(this, "1");
}
/**
* Layout header cell
*/
private void init()
{
setZclass("z-listgroup-header");
span = new Span();
span.setZclass("z-listgroup-icon");
appendChild(span);
span.addEventListener(Events.ON_CLICK, this);
lbl = new Label();
lbl.setStyle("cursor: pointer");
appendChild(lbl);
lbl.addEventListener(Events.ON_CLICK, this);
}
/**
* @return group header text
*/
public String getTitle() {
return title;
}
/**
* Set group header text
* @param title
*/
public void setTitle(String title) {
this.title = title;
lbl.setValue(this.title);
}
/**
* @return true if group is open, false otherwise
*/
public boolean isOpen() {
return open;
}
/**
* Set group state to open or close
* @param open true for open state, false for close state
*/
public void setOpen(boolean open) {
this.open = open;
span.setSclass(this.open ? "z-icon-listgroup-open" : "z-icon-listgroup-close");
}
@Override
public void onEvent(Event e) throws Exception
{
if (e.getName().equals(Events.ON_CLICK))
{
((ListitemGroup) getParent()).setOpen(!isOpen());
}
}
}
}

View File

@ -0,0 +1,154 @@
/***********************************************************************
* This file is part of iDempiere ERP Open Source *
* http://www.idempiere.org *
* *
* Copyright (C) Contributors *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* 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., 51 Franklin Street, Fifth Floor, Boston, *
* MA 02110-1301, USA. *
* *
* Contributors: *
* - hengsin *
**********************************************************************/
package org.adempiere.webui.listbox.renderer;
import org.adempiere.webui.component.ListitemGroup;
import org.adempiere.webui.component.ListitemGroup.ListitemGroupHeader;
import org.zkoss.zul.Listbox;
import org.zkoss.zul.Listcell;
import org.zkoss.zul.Listgroup;
import org.zkoss.zul.ListgroupRendererExt;
import org.zkoss.zul.Listgroupfoot;
import org.zkoss.zul.Listitem;
import org.zkoss.zul.ListitemRenderer;
import org.zkoss.zul.ListitemRendererExt;
/**
* Renderer for {@link Listbox} with single level grouping.<br/>
* Note that due to a class hierarchy issue, this wouldn't works with {@link org.adempiere.webui.component.Listbox}.<br/>
* Note2: not working very well with {@link Listbox#setCheckmark(true)}. Recommended to roll your own checkbox cell if you need multiple selection.
* @author hengsin
* @param <T> Common ancestor type for Group and Item class.
*/
public abstract class AbstractGroupListitemRenderer<T> implements ListitemRenderer<T>, ListitemRendererExt, ListgroupRendererExt {
public AbstractGroupListitemRenderer() {
}
@Override
public Listgroup newListgroup(Listbox listbox) {
Listgroup group = new ListitemGroup();
group.applyProperties();
return group;
}
@Override
public Listgroupfoot newListgroupfoot(Listbox listbox) {
Listgroupfoot groupfoot = new Listgroupfoot();
groupfoot.applyProperties();
return groupfoot;
}
@Override
public Listitem newListitem(Listbox listbox) {
Listitem listitem = new Listitem();
listitem.applyProperties();
return listitem;
}
@Override
public Listcell newListcell(Listitem item) {
return null;// Default Cell
}
@Override
public int getControls() {
return ListitemRendererExt.DETACH_ON_RENDER; // Default Value
}
/**
* @return number of columns for listbox
*/
public abstract int getColumnCount();
/**
* @param data group
* @return group header title
*/
public abstract String getGroupHeaderTitle(T data);
/**
* Renders the data to the specified list item.
* @param item the listitem to render the result.
* @param data item within a group
* @param index the row/list index of the data that is currently being rendered
*/
public abstract void renderListitem(Listitem item, T data, int index);
/**
* Render group
* @param item
* @param data group
* @param index
*/
public void renderGroup(Listitem item, T data, int index)
{
ListitemGroupHeader cell = new ListitemGroupHeader();
cell.applyProperties();
cell.setSpan(getColumnCount());
cell.setTitle(getGroupHeaderTitle(data));
item.appendChild(cell);
}
/**
* Render group footer
* @param item
* @param data footer
* @param index
*/
public void renderGroupfoot(Listitem item, T data, int index)
{
}
@Override
public void render(Listitem item, T data, int index) throws Exception {
if(item instanceof ListitemGroup)
{
item.removeChild(item.getFirstChild());
renderGroup(item, data, index);
}
else
{
if (item.getListgroup() instanceof ListitemGroup)
{
ListitemGroup group = (ListitemGroup) item.getListgroup();
group.add(item);
}
if (item instanceof Listgroupfoot)
{
item.setZclass("z-groupfoot");
renderGroupfoot(item, data, index);
}
else
{
item.setStyle("vertical-align: top;");
item.setValue(data);
renderListitem(item, data, index);
}
}
}
}

View File

@ -0,0 +1,70 @@
/***********************************************************************
* This file is part of iDempiere ERP Open Source *
* http://www.idempiere.org *
* *
* Copyright (C) Contributors *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* 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., 51 Franklin Street, Fifth Floor, Boston, *
* MA 02110-1301, USA. *
* *
* Contributors: *
* - hengsin *
**********************************************************************/
package org.adempiere.webui.listbox.renderer;
import org.zkoss.zul.ListModel;
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;
public abstract class AbstractListitemRenderer<T> implements ListitemRenderer<T>, ListitemRendererExt {
public AbstractListitemRenderer() {
}
@Override
public Listitem newListitem(Listbox listbox) {
Listitem listitem = new Listitem();
listitem.applyProperties();
return listitem;
}
@Override
public Listcell newListcell(Listitem item) {
return null;// Default Cell
}
@Override
public int getControls() {
return ListitemRendererExt.DETACH_ON_RENDER; // Default Value
}
/**
* Renders the data to the specified list item.
* @param item the listitem to render the result.
* @param data data that is returned from {@link ListModel#getElementAt}
* @param index the row/list index of the data that is currently being rendered
*/
public abstract void renderListitem(Listitem item, T data, int index);
@Override
public void render(Listitem item, T data, int index) throws Exception {
item.setStyle("vertical-align: top;");
item.setValue(data);
renderListitem(item, data, index);
}
}

View File

@ -31,3 +31,27 @@ tr.z-group {
.z-group-icon-open:before {
content: "\f0d7";
}
div.z-listbox-body .z-listgroup-header {
padding-top: 4px;
padding-bottom: 4px;
border-bottom: 1px solid rgb(207, 207, 207);
}
.z-listgroup-header-content > .z-listitem-checkable.z-listitem-checkbox {
display: none;
}
.z-listgroup-icon {
display: inline-block;
font-weight: bold;
font-style: normal;
height: 22px;
width: 22px;
font-size: 18px;
padding-top: 2px;
}
.z-icon-listgroup-close::before {
content: "\f105";
}
.z-icon-listgroup-open::before {
content: "\f107";
}