org.icefaces.ace.component.datatable.AutoAdjustRenderedColspan Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of icefaces-ace Show documentation
Show all versions of icefaces-ace Show documentation
${icefaces.product.name} ACE Component Library
The newest version!
/*
* Copyright 2004-2014 ICEsoft Technologies Canada Corp.
*
* 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 org.icefaces.ace.component.datatable;
import org.icefaces.ace.component.column.Column;
import org.icefaces.ace.component.tableconfigpanel.TableConfigPanel;
import org.icefaces.ace.model.table.ColumnModel;
import org.icefaces.ace.model.table.DepthFirstHeadTraversal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* If a header ColumnGroup is used, with multiple row(s), there can be a
* hierarchy of header columns, where a parent with its colspan can stretch
* over several child ones below. In that case, if the parent ceases to be
* rendered, then none of the children or offspring should be rendered.
* Likewise, if every child is not rendered, then the parent should nt be
* either. And if several, but not all, children are not rendered, then the
* parent should be rendered, but have a lesser colspan to account for only
* rendering over the remaining columns. This makes all of these necessary
* adjustments.
*/
public class AutoAdjustRenderedColspan {
public static Map adjustIfAllowed(
TableConfigPanel panel, ColumnModel columnModel) {
if (panel != null && panel.isColumnVisibilityConfigurable()) {
return adjust(columnModel);
}
return null;
}
/**
* @param columnModel
* @return Map
*/
public static Map adjust(ColumnModel columnModel) {
AdjustingRenderedColspanState state = new AdjustingRenderedColspanState();
DepthFirstHeadTraversal.CallbackAdapter callback = new DepthFirstHeadTraversal.
CallbackAdapter()
{
public void afterSpanTraversal(AdjustingRenderedColspanState state,
DepthFirstHeadTraversal.Quantity level,
List columns, List correspondingColumns,
int headerIndex, int bodyIndex) throws RuntimeException {
final boolean parentRendered = state.stack.isEmpty() ? true :
state.stack.get(state.stack.size()-1).isRendered();
List list =
new ArrayList();
for (Column column : columns) {
AdjustedRenderedColspan adj = new AdjustedRenderedColspan(
parentRendered && column.isRendered(), column.getColspan());
list.add(adj);
state.map.put(column.getClientId(), adj);
}
state.stack.add(new AdjustedRenderedColspanSummary(list));
}
public void afterChildrenTraversal(AdjustingRenderedColspanState state,
DepthFirstHeadTraversal.Quantity level, List columns,
List correspondingColumns) throws RuntimeException {
AdjustedRenderedColspanSummary curr = state.stack.remove(
state.stack.size()-1);
for (int i = 0; i < columns.size(); i++) {
boolean r = curr.getList().get(i).isRendered();
columns.get(i).updateRendered(r);
if (correspondingColumns != null) {
Column corr = correspondingColumns.get(i);
if (!corr.isLikelySpecifiedRendered()) {
corr.updateRendered(r);
}
}
}
if (!state.stack.isEmpty()) {
AdjustedRenderedColspanSummary above = state.stack.get(
state.stack.size()-1);
above.applyChildAdjustment(curr);
}
}
};
DepthFirstHeadTraversal
t = new DepthFirstHeadTraversal(columnModel, callback, state);
t.traverse();
return state.map;
}
public static class AdjustedRenderedColspan {
private boolean rendered;
private int colspan;
private int adjustedColspan;
AdjustedRenderedColspan(boolean rendered, int colspan) {
this.rendered = rendered && colspan > 0;
this.colspan = colspan;
this.adjustedColspan = rendered ? colspan : 0;
}
boolean isRendered() { return rendered; }
int getColspan() { return colspan; }
int getAdjustedColspan() { return adjustedColspan; }
// deltaColspan : <= 0 : adjustedColspan - colspan
void applyChildAdjustment(int deltaColspan) {
if (rendered) {
adjustedColspan = Math.max(0, adjustedColspan +
deltaColspan);
if (adjustedColspan == 0) {
rendered = false;
}
}
}
}
private static class AdjustedRenderedColspanSummary {
private List list;
private boolean anyRendered;
AdjustedRenderedColspanSummary(List list) {
this.list = list;
anyRendered = false;
for (AdjustedRenderedColspan adj : list) {
anyRendered |= adj.isRendered();
}
}
public boolean isRendered() { return anyRendered; }
public List getList() { return list; }
// Negative or zero
private int getDeltaColspan() {
int maxColspan = 0;
int maxAdjustedColspan = 0;
for (AdjustedRenderedColspan adj : list) {
maxColspan = Math.max(maxColspan, adj.getColspan());
maxAdjustedColspan = Math.max(maxAdjustedColspan,
adj.getAdjustedColspan());
}
return maxAdjustedColspan - maxColspan;
}
public void applyChildAdjustment(AdjustedRenderedColspanSummary below) {
int deltaColspan = below.getDeltaColspan();
for (AdjustedRenderedColspan adj : list) {
adj.applyChildAdjustment(deltaColspan);
}
}
}
private static class AdjustingRenderedColspanState {
HashMap map;
ArrayList stack;
AdjustingRenderedColspanState() {
map = new HashMap();
stack = new ArrayList();
}
}
}