/*
* Copyright (c) 2010-2016 Evolveum
*
* 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 com.evolveum.midpoint.web.component.data.column;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.web.component.data.BaseSortableDataProvider;
import com.evolveum.midpoint.web.component.data.SelectableDataTable;
import com.evolveum.midpoint.web.component.data.TableHeadersToolbar;
import com.evolveum.midpoint.web.component.util.Selectable;
import com.evolveum.midpoint.web.component.util.VisibleEnableBehaviour;
import org.apache.wicket.Component;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.extensions.markup.html.repeater.data.table.DataTable;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.repeater.data.IDataProvider;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.util.iterator.ComponentHierarchyIterator;
import java.io.Serializable;
import java.util.List;
/**
* @author lazyman
*/
public class CheckBoxHeaderColumn<T extends Serializable> extends CheckBoxColumn<T> {
private static final Trace LOGGER = TraceManager.getTrace(CheckBoxHeaderColumn.class);
public CheckBoxHeaderColumn() {
super(null);
}
private boolean visible = true;
@Override
public Component getHeader(final String componentId) {
final IModel<Boolean> model = new Model<Boolean>(false);
CheckBoxPanel panel = new CheckBoxPanel(componentId, model, getEnabled()) {
@Override
public void onUpdate(AjaxRequestTarget target) {
DataTable table = findParent(DataTable.class);
boolean selected = model.getObject() != null ? model.getObject() : false;
onUpdateHeader(target, selected, table);
}
};
panel.setOutputMarkupId(true);
panel.add(new VisibleEnableBehaviour() {
@Override
public boolean isVisible() {
return CheckBoxHeaderColumn.this.isCheckboxVisible();
}
});
return panel;
}
@Override
public String getCssClass() {
return "icon";
}
protected boolean isCheckboxVisible(){
return visible;
}
public void setCheckboxVisible(boolean visible){
this.visible = visible;
}
/**
* This method is called after select all checkbox is clicked
* @param target
* @param selected
* @param table
*/
protected void onUpdateHeader(AjaxRequestTarget target, boolean selected, DataTable table) {
IDataProvider provider = table.getDataProvider();
if (!(provider instanceof BaseSortableDataProvider)) {
LOGGER.debug("Select all checkbox work only with {} provider type. Current provider is type of {}.",
new Object[]{BaseSortableDataProvider.class.getName(), provider.getClass().getName()});
}
//update selected flag in model dto objects based on select all header state
BaseSortableDataProvider baseProvider = (BaseSortableDataProvider) provider;
List<T> objects = baseProvider.getAvailableData();
for (T object : objects) {
if (object instanceof Selectable) {
Selectable selectable = (Selectable) object;
selectable.setSelected(selected);
}
}
//refresh rows with ajax
ComponentHierarchyIterator iterator = table.visitChildren(SelectableDataTable.SelectableRowItem.class);
while (iterator.hasNext()) {
SelectableDataTable.SelectableRowItem row = (SelectableDataTable.SelectableRowItem) iterator.next();
if (!row.getOutputMarkupId()) {
//we skip rows that doesn't have outputMarkupId set to true (it would fail)
continue;
}
target.add(row);
}
}
public static <T> boolean shouldBeHeaderSelected(DataTable table) {
boolean selectedAll = true;
BaseSortableDataProvider baseProvider = (BaseSortableDataProvider) table.getDataProvider();
List<T> objects = baseProvider.getAvailableData();
if (objects == null || objects.isEmpty()) {
return false;
}
for (T object : objects) {
if (object instanceof Selectable) {
Selectable selectable = (Selectable) object;
selectedAll &= selectable.isSelected();
}
}
return selectedAll;
}
/**
* This method is called after checkbox in row is updated
*/
@Override
protected void onUpdateRow(AjaxRequestTarget target, DataTable table, IModel<T> rowModel) {
//update header checkbox
CheckBoxPanel header = findCheckBoxColumnHeader(table);
if (header == null) {
return;
}
header.getPanelComponent().setModelObject(shouldBeHeaderSelected(table));
target.add(header);
}
public static CheckBoxPanel findCheckBoxColumnHeader(DataTable table) {
WebMarkupContainer topToolbars = table.getTopToolbars();
ComponentHierarchyIterator iterator = topToolbars.visitChildren(TableHeadersToolbar.class);
if (!iterator.hasNext()) {
return null;
}
TableHeadersToolbar toolbar = (TableHeadersToolbar) iterator.next();
// simple attempt to find checkbox which is header for our column
// todo: this search will fail if there are more checkbox header columns (which is not supported now,
// because Selectable.F_SELECTED is hardcoded all over the place...
iterator = toolbar.visitChildren(CheckBoxPanel.class);
while (iterator.hasNext()) {
Component c = iterator.next();
if (!c.getOutputMarkupId()) {
continue;
}
return (CheckBoxPanel) c;
}
return null;
}
}