tools.dynamia.zk.viewers.table.TableView Maven / Gradle / Ivy
/*
* Copyright (C) 2023 Dynamia Soluciones IT S.A.S - NIT 900302344-1
* Colombia / South America
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package tools.dynamia.zk.viewers.table;
import org.zkoss.bind.Binder;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zul.AbstractListModel;
import org.zkoss.zul.ListModel;
import org.zkoss.zul.Listbox;
import org.zkoss.zul.Listfoot;
import org.zkoss.zul.Listhead;
import org.zkoss.zul.Listitem;
import org.zkoss.zul.ListitemRenderer;
import org.zkoss.zul.Menupopup;
import tools.dynamia.commons.MapBuilder;
import tools.dynamia.commons.PropertyChangeListenerContainer;
import tools.dynamia.commons.collect.PagedList;
import tools.dynamia.domain.fx.Functions;
import tools.dynamia.domain.fx.MultiFunctionProcessor;
import tools.dynamia.domain.query.DataSet;
import tools.dynamia.viewers.TableViewComponent;
import tools.dynamia.viewers.View;
import tools.dynamia.viewers.ViewDescriptor;
import tools.dynamia.viewers.util.Viewers;
import tools.dynamia.zk.BindingComponentIndex;
import tools.dynamia.zk.ComponentAliasIndex;
import tools.dynamia.zk.ui.CanBeReadonly;
import tools.dynamia.zk.util.ZKBindingUtil;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.function.Consumer;
/**
* @author Mario A. Serrano Leones
*/
@SuppressWarnings("unchecked")
public class TableView extends Listbox implements TableViewComponent, CanBeReadonly {
static {
BindingComponentIndex.getInstance().put("value", TableView.class);
ComponentAliasIndex.getInstance().add(TableView.class);
}
/**
*
*/
private static final long serialVersionUID = 1L;
/**
* Event to listen double click events in ListItmes
*/
public static final String ON_ITEM_DOUBLE_CLICK = "onItemDoubleClick";
public static final String ON_ITEM_CLICK = "onItemDoubleClick";
public static final String ON_ITEMS_RENDERED = "onItemsRendered";
public static final String ON_VALUE_CHANGED = "onValueChanged";
public static final String ON_MODEL_CHANGED = "onModelChanged";
private List value;
private ViewDescriptor viewDescriptor;
private boolean showRowNumber = true;
private List defaultValue;
private View parentView;
private String orderBy;
private int maxResults;
private Menupopup contextMenu;
private Object source;
private Consumer onSourceChange;
private boolean projection;
private PagedList pageList;
private boolean readonly;
private List footersWithFunctions;
private MultiFunctionProcessor multiFunctionProcesor;
public TableView() {
}
public TableView(ViewDescriptor viewDescriptor) {
this.viewDescriptor = viewDescriptor;
}
public int getAbsoluteIndex(Listitem item) {
int ai = item.getIndex() + 1;
if (pageList != null) {
int pai = getPaginal().getPageSize() * getPaginal().getActivePage();
ai += pai;
}
return ai;
}
@Override
public List getValue() {
return value;
}
@Override
public void setValue(DataSet> dataSet) {
setValue(dataSet.getData());
}
@Override
public void setValue(List value) {
if (value instanceof PagedList) {
this.pageList = (PagedList) value;
// value = this.pageList.getDataSource().getPageData();
} else {
this.pageList = null;
}
boolean changed = false;
if (defaultValue != null && !defaultValue.isEmpty()) {
this.value = new ArrayList<>(defaultValue);
if (value != null) {
this.value.addAll(value);
changed = true;
}
} else {
try {
if ((this.value == null && value != null) || (this.value != null && value == null) ||
(this.value != null && value != null && this.value.size() != value.size()) || this.value != value) {
changed = true;
}
} catch (NoSuchElementException e) {
changed = true;
}
this.value = value;
}
if (this.value == null) {
setModel((ListModel) null);
} else {
setModel(new TableViewModel<>(this.value, true, isMultiple()));
}
if (changed) {
Events.postEvent(ON_VALUE_CHANGED, this, this.value);
}
}
@Override
public T getSelected() {
if (getSelectedItem() != null) {
return getSelectedItem().getValue();
} else {
return null;
}
}
@Override
public void setSelected(Object selected) {
if (selected != null && getModel() instanceof AbstractListModel model) {
model.addToSelection(selected);
}
}
public void setDefaultValue(List defaultValue) {
this.defaultValue = defaultValue;
}
@Override
public TableFieldComponent getTableFieldComponent(String fieldName, int rowIndex) {
try {
Listitem item = getItemAtIndex(rowIndex);
Map tfcMap = (Map) item
.getAttribute("TABLE_FIELD_COMPONENTS");
return tfcMap.get(fieldName);
} catch (Exception e) {
return null;
}
}
@Override
public TableFieldComponent getTableFieldComponent(String fieldName, Object item) {
try {
if (item instanceof Component component) {
Map tfcMap = (Map) component
.getAttribute("TABLE_FIELD_COMPONENTS");
return tfcMap.get(fieldName);
}
} catch (Exception e) {
return null;
}
return null;
}
@Override
public void clear() {
setValue((List) null);
}
public Listitem getListItemByValue(T value) {
Listitem target = null;
for (Object obj : getItems()) {
Listitem item = (Listitem) obj;
if (item.getValue().equals(value)) {
target = item;
break;
}
}
return target;
}
@Override
public ViewDescriptor getViewDescriptor() {
return viewDescriptor;
}
@Override
public void setViewDescriptor(ViewDescriptor viewDescriptor) {
this.viewDescriptor = viewDescriptor;
}
@Override
public void setItemRenderer(ListitemRenderer renderer) {
super.setItemRenderer(renderer);
if (renderer instanceof TableViewRowRenderer tvrr) {
tvrr.setViewDescriptor(viewDescriptor);
tvrr.setTableView(this);
}
}
@Override
public void setShowRowNumber(boolean showRowNumber) {
this.showRowNumber = showRowNumber;
}
@Override
public boolean isShowRowNumber() {
return showRowNumber;
}
@Override
public boolean isListitemSelected() {
return getSelectedItem() != null;
}
@Override
public View getParentView() {
return parentView;
}
@Override
public void setParentView(View parentView) {
this.parentView = parentView;
}
public String getOrderBy() {
return orderBy;
}
public void setOrderBy(String orderBy) {
this.orderBy = orderBy;
}
public Menupopup getContextMenu() {
return contextMenu;
}
public void setContextMenu(Menupopup contextMenu) {
this.contextMenu = contextMenu;
}
@Override
public TableViewFooter getFooter(String fieldName) {
Listfoot foot = getListfoot();
if (foot != null) {
List footers = foot.getChildren();
for (TableViewFooter listfooter : footers) {
Object fn = listfooter.getAttribute("field-name");
if (fn != null && fn.toString().equals(fieldName)) {
return listfooter;
}
}
}
return null;
}
@Override
public TableViewHeader getHeader(String fieldName) {
Listhead head = getListhead();
if (head != null) {
List headers = head.getChildren();
for (TableViewHeader header : headers) {
Object fn = header.getAttribute("field-name");
if (fn != null && fn.toString().equals(fieldName)) {
return header;
}
}
}
return null;
}
public void updateUI() {
Events.postEvent(ON_MODEL_CHANGED, this, this.value);
Events.postEvent(ON_VALUE_CHANGED, this, this.value);
}
@Override
public boolean isEmpty() {
return getModel() == null || getModel().getSize() == 0;
}
@Override
public Object getSource() {
return source;
}
@Override
public void setSource(Object source) {
this.source = source;
if (onSourceChange != null) {
onSourceChange.accept(source);
}
if (source instanceof PropertyChangeListenerContainer) {
((PropertyChangeListenerContainer) source).addPropertyChangeListener(l -> computeFooters());
}
}
public int getMaxResults() {
return maxResults;
}
public void setMaxResults(int maxResults) {
this.maxResults = maxResults;
}
public boolean isProjection() {
return projection;
}
public void setProjection(boolean projection) {
this.projection = projection;
}
@Override
public boolean isReadonly() {
return readonly;
}
@Override
public void setReadonly(boolean readonly) {
boolean old = this.readonly;
this.readonly = readonly;
if (old != this.readonly) {
renderAll();
}
}
/**
* Reload component binding for selected row
*/
public void updateSelectedItem() {
try {
var selectRow = getSelectedItem();
var binder = (Binder) selectRow.getAttribute(TableViewRowRenderer.ROW_BINDER_NAME);
ZKBindingUtil.bindBean(selectRow, Viewers.BEAN, selectRow.getValue());
binder.loadComponent(selectRow, false);
} catch (Exception e) {
//cannot doit
}
}
public void onSourceChanged(Consumer onSourceChange) {
this.onSourceChange = onSourceChange;
}
void setFootersWithFunctions(List footersWithFunctions) {
this.footersWithFunctions = footersWithFunctions;
}
List getFootersWithFunctions() {
return footersWithFunctions;
}
/**
* Update all footer with functions
*/
public void computeFooters() {
try {
if (footersWithFunctions != null) {
footersWithFunctions.forEach(TableViewFooter::clear);
if (value != null) {
if (multiFunctionProcesor != null) {
var result = multiFunctionProcesor.compute(value, new HashMap<>(), footersWithFunctions);
result.forEach((f, v) -> footersWithFunctions.stream()
.filter(ft -> ft.equals(f)).findFirst()
.ifPresent(tableViewFooter -> tableViewFooter.setValue(v)));
} else {
footersWithFunctions.forEach(footer -> {
if (value instanceof Collection) {
if (!((Collection) value).isEmpty()) {
Map args = MapBuilder.put("property", footer.getField().getName());
Object result = Functions.compute(footer.getFunction(), value, args);
footer.setValue(result);
}
}
});
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void setMultiFunctionProcesor(MultiFunctionProcessor multiFunctionProcesor) {
this.multiFunctionProcesor = multiFunctionProcesor;
}
public MultiFunctionProcessor getMultiFunctionProcesor() {
return multiFunctionProcesor;
}
}