Community
Participate
Working Groups
The following code with Eclipse 3.1 works, but with Eclipse 3.2 I have problems when I change input. Exactly when you call for at least the second time viewer.setInput(movementTableItemProvider); viewer.setItemCount(movementTableItemProvider.getItemCount()); after setInput this happens: ----------------------------------------------------------------------- TableView$ViewContentProvider.updateElement(int) line: 109 TableViewer.virtualSetSelectionToWidget(List, boolean) line: 1151 TableViewer.setSelectionToWidget(List, boolean) line: 1090 TableViewer(StructuredViewer).setSelectionToWidget(ISelection, boolean) line: 1494 TableViewer(StructuredViewer).preservingSelection(Runnable) line: 1208 TableViewer(StructuredViewer).refresh(Object) line: 1262 TableViewer(StructuredViewer).refresh() line: 1221 TableViewer.inputChanged(Object, Object) line: 745 TableViewer(ContentViewer).setInput(Object) line: 248 TableViewer(StructuredViewer).setInput(Object) line: 1417 TableView.changeInput(ISelection) line: 277 ------------------------------------------------------------------------ When the new input has fewer items than the old one, the method updateElement is called for all items of the table not only the visible ones. These items doesn't exist at all with new input (the setItemCount is called after setInput) (I don't have any Selection on the table and I'm not interested to preserve it when I change input.) If I call setItemCount before setInput, in my case I don't have problems with non existent items, but the table is still not virtual because the updateElement method is called for every index. With viewer.setItemCount(0); viewer.setInput(movementTableItemProvider); viewer.setItemCount(movementTableItemProvider.getItemCount()); it seems I turn around the bug. ********************************************************************* ********************************************************************* public class TableView extends ViewPart implements ISelectionListener, IPartListener2 { public static final String ID = "net.mydomain.myrcpapp.views.TableView"; private TableViewer viewer; private ITableItemProviderFactory tableItemProviderFactory; private Action action1; private Action action2; private Action doubleClickAction; class ViewContentProvider implements ILazyContentProvider { public void inputChanged(Viewer v, Object oldInput, Object newInput) { if (newInput instanceof TableItemProvider) { viewer.getTable().setTopIndex(0); if (oldInput instanceof TableItemProvider) { if (!((TableItemProvider) oldInput).getColumnHeaders() .equals( ((TableItemProvider) newInput).getColumnHeaders())) { setColumns((TableItemProvider) newInput); } } else if (oldInput == null) { setColumns((TableItemProvider) newInput); } } } public void dispose() { } public void updateElement(int index) { if (viewer.getInput() instanceof TableItemProvider) { viewer.replace( ((TableItemProvider) viewer.getInput()).getTableItem(index), index); // System.out.println("TableItem: " + index); // System.out.println("ItemCount: " + // viewer.getTable().getItems().length); } } } class ViewLabelProvider extends LabelProvider implements ITableLabelProvider { public String getColumnText(Object obj, int index) { return ((ITableItem) obj).getField(index); } public Image getColumnImage(Object obj, int index) { return getImage(obj); } public Image getImage(Object obj) { return PlatformUI.getWorkbench().getSharedImages ().getImage( ISharedImages.IMG_OBJ_ELEMENT); } } /* * class NameSorter extends ViewerSorter { } */ /** * The constructor. */ public TableView() { } public void createPartControl(Composite parent) { viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.VIRTUAL); viewer.setContentProvider(new ViewContentProvider()); viewer.setLabelProvider(new ViewLabelProvider()); // viewer.setSorter(new NameSorter()); viewer.setUseHashlookup(true); // getViewSite().getPage().addSelectionListener(this); // TODO controllare getViewSite().getPage().addPartListener(this); makeActions(); hookContextMenu(); hookDoubleClickAction(); contributeToActionBars(); } private void hookContextMenu() { MenuManager menuMgr = new MenuManager("#PopupMenu"); menuMgr.setRemoveAllWhenShown(true); menuMgr.addMenuListener(new IMenuListener() { public void menuAboutToShow(IMenuManager manager) { TableView.this.fillContextMenu(manager); } }); Menu menu = menuMgr.createContextMenu(viewer.getControl()); viewer.getControl().setMenu(menu); getSite().registerContextMenu(menuMgr, viewer); } private void contributeToActionBars() { IActionBars bars = getViewSite().getActionBars(); fillLocalPullDown(bars.getMenuManager()); fillLocalToolBar(bars.getToolBarManager()); } private void fillLocalPullDown(IMenuManager manager) { manager.add(action1); manager.add(new Separator()); manager.add(action2); } private void fillContextMenu(IMenuManager manager) { manager.add(action1); manager.add(action2); // Other plug-ins can contribute there actions here manager.add(new Separator (IWorkbenchActionConstants.MB_ADDITIONS)); } private void fillLocalToolBar(IToolBarManager manager) { manager.add(action1); manager.add(action2); } private void makeActions() { action1 = new Action() { public void run() { showMessage("Action 1 executed"); } }; action1.setText("Action 1"); action1.setToolTipText("Action 1 tooltip"); action1.setImageDescriptor(PlatformUI.getWorkbench() .getSharedImages() .getImageDescriptor (ISharedImages.IMG_OBJS_INFO_TSK)); action2 = new Action() { public void run() { showMessage("Action 2 executed"); } }; action2.setText("Action 2"); action2.setToolTipText("Action 2 tooltip"); action2.setImageDescriptor(PlatformUI.getWorkbench() .getSharedImages() .getImageDescriptor (ISharedImages.IMG_OBJS_INFO_TSK)); doubleClickAction = new Action() { public void run() { ISelection selection = viewer.getSelection(); Object obj = ((IStructuredSelection) selection).getFirstElement(); showMessage("Double-click detected on " + obj.toString()); } }; } private void hookDoubleClickAction() { viewer.addDoubleClickListener(new IDoubleClickListener() { public void doubleClick(DoubleClickEvent event) { doubleClickAction.run(); } }); } private void showMessage(String message) { MessageDialog.openInformation(viewer.getControl().getShell(), "TableView", message); } /** * Passing the focus request to the viewer's control. */ public void setFocus() { viewer.getControl().setFocus(); } private void changeInput(ISelection navigationViewSelection) { if (navigationViewSelection instanceof IStructuredSelection) { Object obj = ((IStructuredSelection) navigationViewSelection).getFirstElement(); if (obj instanceof ITableItemProviderFactory) { if (!obj.equals(tableItemProviderFactory)) { tableItemProviderFactory = (ITableItemProviderFactory) obj; TableItemProvider movementTableItemProvider = tableItemProviderFactory.getTableItemProvider(); viewer.setInput (movementTableItemProvider); viewer.setItemCount (movementTableItemProvider.getItemCount()); } } } } private void setColumns(TableItemProvider tableItemProvider) { Table virtualTable = viewer.getTable(); virtualTable.setRedraw(false); // virtualTable.setTopIndex(0); while (virtualTable.getColumnCount() > 0) { int lastOne = virtualTable.getColumnCount() - 1; virtualTable.getColumn(lastOne).dispose(); } String[] columnHeaders = tableItemProvider.getColumnHeaders(); for (int i = 0; i < columnHeaders.length; i++) { TableColumn column = new TableColumn(virtualTable, SWT.RIGHT); column.setText(columnHeaders[i]); column.setWidth(120); column.setMoveable(true); } virtualTable.setRedraw(true); virtualTable.setHeaderVisible(true); } // TODO viene chiamata anche per la stessa selezione! public void selectionChanged(IWorkbenchPart part, ISelection selection) { changeInput(selection); } public void partActivated(IWorkbenchPartReference partRef) { // TODO Auto-generated method stub } public void partBroughtToTop(IWorkbenchPartReference partRef) { // TODO Auto-generated method stub } public void partClosed(IWorkbenchPartReference partRef) { // TODO Auto-generated method stub } public void partDeactivated(IWorkbenchPartReference partRef) { // TODO Auto-generated method stub } public void partOpened(IWorkbenchPartReference partRef) { // TODO Auto-generated method stub } public void partHidden(IWorkbenchPartReference partRef) { if (partRef.getId().equals(ID)) { getViewSite().getPage().removeSelectionListener(this); } } public void partVisible(IWorkbenchPartReference partRef) { if (partRef.getId().equals(ID)) { getViewSite().getPage().addSelectionListener(this); changeInput(getViewSite().getPage().getSelection (NavigationView.ID)); } } public void partInputChanged(IWorkbenchPartReference partRef) { // TODO Auto-generated method stub } }
Giovanni, what exactly happens on line 109 of TableView$ViewContentProvider ? This looks like a stack trace, but I don't see which exception is being thrown.
(In reply to comment #1) > Giovanni, what exactly happens on line 109 of TableView$ViewContentProvider ? > This looks like a stack trace, but I don't see which exception is being thrown. That is a stack trace of a debug session. I don't have any exception, but a different behavior not present in Eclipse 3.1 causing the call of updateElement for every element. On line 109 of my code I put viewer.replace(((TableItemProvider) viewer.getInput()).getTableItem(index), index); and in your code at virtualSetSelectionToWidget(List list, boolean reveal) of Tableviewer class the following piece of code retrieve all table items. Your comment seems reveal what I'm trying to explain. if(getContentProvider() instanceof ILazyContentProvider){ ILazyContentProvider provider = (ILazyContentProvider) getContentProvider(); //Now go through it again until all is done or we are no longer virtual //This may create all items so it is not a good //idea in general. //Use #setSelection (int [] indices,boolean reveal) instead for (int i = 0; i < getTable().getItemCount(); i++) { provider.updateElement(i); TableItem item = getTable().getItem(i); if(virtualElements.contains(item.getData())){ indices[count++] = i; virtualElements.remove(item.getData()); if (firstItem == null) firstItem = item; } } }
This is related to bug 111743 and might be a dupe.
After staring at this for some time, my recommendation is to call viewer.setItemCount from within your lazy content provider's inputChanged method. Please let me know if this works for you. If this solves the issue, I'll improve the Javadoc so that others who follow you hopefully don't fall into the same trap.
(In reply to comment #4) > After staring at this for some time, my recommendation is to call > viewer.setItemCount from within your lazy content provider's inputChanged method. > Please let me know if this works for you. If this solves the issue, I'll improve > the Javadoc so that others who follow you hopefully don't fall into the same trap. It doesn't work, because all items are retrieved instead of only the visible ones. It works only with this sequence (not in inputChanged method). viewer.setItemCount(0); viewer.setInput(myNewInput); viewer.setItemCount(myNewInput.getItemCount()); So when you scroll, new items are retrieved as needed.
OK, but now you are seeing another bug (see bug 111743), which I have fixed yesterday.
(In reply to comment #6) > OK, but now you are seeing another bug (see bug 111743), which I have fixed > yesterday. I download Eclipse N20051030-0010 and it works. Another question... If I call setItemCount(300) and then setItemtCount(100) should I care to release/dispose something? In this build seems present another bug. When I start my rcp app, the tableviewer is empty, because the navigation view who controls the filling of table doesn't receive at startup the default focus on the first Tree node as it happend with Eclipse 3.1.
Setting the item count to a smaller number will dispose of the items that are no longer needed. Marking this as worksforme since I did not change any code for this. Regarding the bug you describe in comment #7, could you open another bug and describe it in more detail? Thanks!