| Summary: | Large Virtual Tree request items with an index higher than itemCount | ||
|---|---|---|---|
| Product: | [RT] RAP | Reporter: | Moritz Post <mpost> |
| Component: | RWT | Assignee: | Project Inbox <rap-inbox> |
| Status: | RESOLVED INVALID | QA Contact: | |
| Severity: | normal | ||
| Priority: | P3 | ||
| Version: | 1.5 | ||
| Target Milestone: | --- | ||
| Hardware: | PC | ||
| OS: | Windows 7 | ||
| Whiteboard: | |||
|
Description
Moritz Post
Moritz, could you provide a snippet to reproduce the issue? My favorite answer :)
Tree:
private void createVirtualTree( Display display, Composite parent ) {
Composite composite = new Composite( parent, SWT.NONE );
composite.setLayoutData( GridDataFactory.fillDefaults().grab( true, true ) );
GridLayout layout = new GridLayout( 1, false );
layout.marginHeight = 0;
layout.marginWidth = 0;
composite.setLayout( layout );
tab2.setControl( composite );
final TreeViewer treeViewer = new TreeViewer( composite, SWT.VIRTUAL
| SWT.H_SCROLL
| SWT.V_SCROLL );
treeViewer.setUseHashlookup( true );
treeViewer.setContentProvider( new LazyContentProvider( treeViewer ) );
treeViewer.setLabelProvider( new LazyLabelProvider() );
treeViewer.setInput( new TodoMockModel() );
treeViewer.getTree().setToolTipText( "Large virtual tree" );
treeViewer.getTree().setLayoutData( GridDataFactory.fillDefaults().grab( true, true ).create() );
}
Provider:
public class LazyContentProvider implements ILazyTreeContentProvider {
private static final long serialVersionUID = 1L;
private final TreeViewer viewer;
public LazyContentProvider( TreeViewer viewer ) {
this.viewer = viewer;
}
public Object getParent( Object element ) {
Object result = null;
if( element instanceof Todo ) {
result = ( ( Todo )element ).getParent();
}
return result;
}
public void updateElement( Object parent, int index ) {
if( parent instanceof Category ) {
Category parentItem = ( Category )parent;
Todo child = parentItem.getTodos().get( index );
if( child != null ) {
viewer.replace( parent, index, child );
viewer.setChildCount( child, 0 );
}
} else if( parent instanceof TodoMockModel ) {
TodoMockModel parentItem = ( TodoMockModel )parent;
List<Category> manyCategories = parentItem.getManyCategories();
Category child = manyCategories.get( index );
if( child != null ) {
viewer.replace( parent, index, child );
viewer.setChildCount( child, manyCategories.size() );
}
}
}
public void updateChildCount( Object element, int currentChildCount ) {
if( element instanceof Category ) {
Category category = ( Category )element;
int childCount = category.getTodos().size();
if( childCount != currentChildCount ) {
viewer.setChildCount( element, childCount );
}
} else if( element instanceof TodoMockModel ) {
TodoMockModel model = ( TodoMockModel )element;
int childCount = model.getManyCategories().size();
if( childCount != currentChildCount ) {
viewer.setChildCount( element, childCount );
}
}
}
public void inputChanged( Viewer viewer, Object oldInput, Object newInput ) {
}
public void dispose() {
// nothing
}
}
public final class LazyLabelProvider extends CellLabelProvider {
private static final long serialVersionUID = 1L;
@Override
public void update( final ViewerCell cell ) {
Object element = cell.getElement();
if( element instanceof Category ) {
Category category = ( Category )element;
cell.setText( category.getName() );
} else if( element instanceof Todo ) {
Todo todo = ( Todo )element;
cell.setText( todo.getTitle() );
}
}
@Override
public String getToolTipText( final Object element ) {
return "";
}
}
Model:
public class TodoMockModel {
public List<Category> getManyCategories() {
List<Category> categories = new ArrayList<Category>();
for( int i = 0; i < 500; i++ ) {
Category cat = new Category();
cat.setName( "Category " + i );
categories.add( cat );
for( int j = 0; j < 100; j++ ) {
Todo todo = new Todo( cat, "(Cat " + i + ") -> Todo " + j );
cat.getTodos().add( todo );
}
}
return categories;
}
}
public class Todo {
private String title = "";
private String description = "";
private final Category parent;
public Todo( Category parent, String summary ) {
this.parent = parent;
this.title = summary;
}
public Todo( Category parent, String summary, String description ) {
this.parent = parent;
this.title = summary;
this.description = description;
}
public Category getParent() {
return parent;
}
public String getTitle() {
return title;
}
public void setTitle( String title ) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription( String description ) {
this.description = description;
}
@Override
public String toString() {
return "Todo [title=" + title + ", description=" + description + "]";
}
}
public class Category {
private String name;
private int sort;
private final List<Todo> todos = new ArrayList<Todo>();
public String getName() {
return name;
}
public void setName( String name ) {
this.name = name;
}
public int getSort() {
return sort;
}
public void setSort( int sort ) {
this.sort = sort;
}
public List<Todo> getTodos() {
return todos;
}
@Override
public String toString() {
return "Category [name=" + name + ", sort=" + sort + ", todos=" + todos + "]";
}
}
Remove the line tab2.setControl( composite ); in the createTree method. I think that this is a programming error. Replacing this line in LazyContentProvider#updateElement: -------------------- viewer.setChildCount( child, manyCategories.size() ); -------------------- with: -------------------- viewer.setChildCount( child, child.getTodos().size() ); -------------------- solves the problem. Before, for every child (TreeItem) the itemCount was set to 500 ( manyCategories.size() ), but the element list has only 100 elements. Your assumption was correct ivan. Closed as invalid. |