/*
* Copyright 2011 Vaadin Ltd.
*
* 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.vaadin.ui;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import com.vaadin.data.Collapsible;
import com.vaadin.data.Container;
import com.vaadin.data.Container.Hierarchical;
import com.vaadin.data.Container.ItemSetChangeEvent;
import com.vaadin.data.util.ContainerHierarchicalWrapper;
import com.vaadin.data.util.HierarchicalContainer;
import com.vaadin.data.util.HierarchicalContainerOrderedWrapper;
import com.vaadin.shared.ui.treetable.TreeTableConstants;
import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
import com.vaadin.terminal.Resource;
import com.vaadin.ui.Tree.CollapseEvent;
import com.vaadin.ui.Tree.CollapseListener;
import com.vaadin.ui.Tree.ExpandEvent;
import com.vaadin.ui.Tree.ExpandListener;
/**
* TreeTable extends the {@link Table} component so that it can also visualize a
* hierarchy of its Items in a similar manner that {@link Tree} does. The tree
* hierarchy is always displayed in the first actual column of the TreeTable.
*
* The TreeTable supports the usual {@link Table} features like lazy loading, so
* it should be no problem to display lots of items at once. Only required rows
* and some cache rows are sent to the client.
*
* TreeTable supports standard {@link Hierarchical} container interfaces, but
* also a more fine tuned version - {@link Collapsible}. A container
* implementing the {@link Collapsible} interface stores the collapsed/expanded
* state internally and can this way scale better on the server side than with
* standard Hierarchical implementations. Developer must however note that
* {@link Collapsible} containers can not be shared among several users as they
* share UI state in the container.
*/
@SuppressWarnings({ "serial" })
public class TreeTable extends Table implements Hierarchical {
private interface ContainerStrategy extends Serializable {
public int size();
public boolean isNodeOpen(Object itemId);
public int getDepth(Object itemId);
public void toggleChildVisibility(Object itemId);
public Object getIdByIndex(int index);
public int indexOfId(Object id);
public Object nextItemId(Object itemId);
public Object lastItemId();
public Object prevItemId(Object itemId);
public boolean isLastId(Object itemId);
public Collection> getItemIds();
public void containerItemSetChange(ItemSetChangeEvent event);
}
private abstract class AbstractStrategy implements ContainerStrategy {
/**
* Consider adding getDepth to {@link Collapsible}, might help
* scalability with some container implementations.
*/
@Override
public int getDepth(Object itemId) {
int depth = 0;
Hierarchical hierarchicalContainer = getContainerDataSource();
while (!hierarchicalContainer.isRoot(itemId)) {
depth++;
itemId = hierarchicalContainer.getParent(itemId);
}
return depth;
}
@Override
public void containerItemSetChange(ItemSetChangeEvent event) {
}
}
/**
* This strategy is used if current container implements {@link Collapsible}
* .
*
* open-collapsed logic diverted to container, otherwise use default
* implementations.
*/
private class CollapsibleStrategy extends AbstractStrategy {
private Collapsible c() {
return (Collapsible) getContainerDataSource();
}
@Override
public void toggleChildVisibility(Object itemId) {
c().setCollapsed(itemId, !c().isCollapsed(itemId));
}
@Override
public boolean isNodeOpen(Object itemId) {
return !c().isCollapsed(itemId);
}
@Override
public int size() {
return TreeTable.super.size();
}
@Override
public Object getIdByIndex(int index) {
return TreeTable.super.getIdByIndex(index);
}
@Override
public int indexOfId(Object id) {
return TreeTable.super.indexOfId(id);
}
@Override
public boolean isLastId(Object itemId) {
// using the default impl
return TreeTable.super.isLastId(itemId);
}
@Override
public Object lastItemId() {
// using the default impl
return TreeTable.super.lastItemId();
}
@Override
public Object nextItemId(Object itemId) {
return TreeTable.super.nextItemId(itemId);
}
@Override
public Object prevItemId(Object itemId) {
return TreeTable.super.prevItemId(itemId);
}
@Override
public Collection> getItemIds() {
return TreeTable.super.getItemIds();
}
}
/**
* Strategy for Hierarchical but not Collapsible container like
* {@link HierarchicalContainer}.
*
* Store collapsed/open states internally, fool Table to use preorder when
* accessing items from container via Ordered/Indexed methods.
*/
private class HierarchicalStrategy extends AbstractStrategy {
private final HashSet