Bug 163432 - Add methods to check item visibility in Tables and Trees
Summary: Add methods to check item visibility in Tables and Trees
Status: NEW
Alias: None
Product: Platform
Classification: Eclipse Project
Component: SWT (show other bugs)
Version: 3.3   Edit
Hardware: All All
: P3 enhancement with 2 votes (vote)
Target Milestone: ---   Edit
Assignee: Steve Northover CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-11-04 06:12 EST by Nicolas Richeton CLA
Modified: 2019-09-06 15:36 EDT (History)
6 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Nicolas Richeton CLA 2006-11-04 06:12:59 EST
There is currently no way to check if a TableItem (or a TreeItem) is in the visible area of its parent and how many item a widget can display.

This would allow to clear items and dispose images  when they are not visible, in order to reduce the memory and handle usage.

My use case :
I'm working on a photo sharing application in which i display a lot of different images (3000+) in a table and in a custom widget. These widgets are both using the SWT.VIRTUAL mode, but I don't want to have too many images in memory in the same time, so I have to dispose them when they are not used anymore.   (see http://sharemedia.free.fr/features.php?lang=en)

With the current API, I had to use a kind of cache with a limited size (about 40 images for the table and 200 for my custom widget).
I catch the Paint event on each item and i add the image in the cache if it was not already in it. When the cache reaches its limit, the oldest image is diposed.

This works great, but only when the number of visible item is lower than the cache capacity. In this last case, each image is disposed and created again when a paint event occurs : everything become far too slow.  (The number of displayed items change with the screen resolution and the window / view size). As a workaround , I increased the cache size, but I often have 40+200 images in memory when only 20 are visible.

The API enhancements that could help in the case are :
- A way to get how many items a table can display in its curent size.
- A method that check if an item is in the visible area of its parent.
- maybe visible/invisible events which fire when an item's state changes.
Comment 1 Steve Northover CLA 2006-11-07 08:48:33 EST
Will this work for you:

import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.layout.*;

public class CacheTable {
static int cacheCount;
static final int CACHE_SIZE = 32;
static void checkCache (Table table) {
	if (cacheCount++ < CACHE_SIZE) return;
	cacheCount = 0;
	Rectangle clientRect = table.getClientArea ();
	int topIndex = table.getTopIndex ();
	int bottomIndex = topIndex + 1;
	while (bottomIndex < table.getItemCount ()) {
		Rectangle itemRect = table.getItem (bottomIndex).getBounds ();
		if (itemRect.y > clientRect.y + clientRect.height) {
			break;
		}
		bottomIndex++;
	}
	if (topIndex != 0) {
		System.out.println("top clear " + 0 + " " + (topIndex - 1));
		table.clear (0, topIndex - 1);
	}
	if (bottomIndex != table.getItemCount ()) {
		System.out.println("bottom clear " + bottomIndex + " " + (table.getItemCount () - 1));
		table.clear (bottomIndex, table.getItemCount () - 1);
	}
}
public static void main (String [] args) {
	Display display = new Display ();
	Shell shell = new Shell (display);
	shell.setLayout (new FillLayout ());
	final Table table = new Table (shell, SWT.VIRTUAL);
	table.setItemCount (1000);
	table.addListener (SWT.SetData, new Listener () {
		public void handleEvent (Event e) {
			checkCache (table);
			TableItem item = (TableItem) e.item;
			int index = table.indexOf (item);
			item.setText ("Item " + index);
		}
	});
	shell.setSize (200, 200);
	shell.open ();
	while (!shell.isDisposed ()) {
		if (!display.readAndDispatch ()) display.sleep ();
	}
	display.dispose ();
}
}
Comment 2 Nicolas Richeton CLA 2006-12-11 15:10:44 EST
I believe this should work, thanks (I didn't have time to try it yet.)

Maybe adding a method like getBottomIndex() would make things easier. I don't know the internals of table, but if this value is known by the Table widget it would make things faster (no need to loop on visible items each time the slider is moved).

What do you think of this ?
 
Comment 3 Steve Northover CLA 2006-12-11 17:57:05 EST
I'm not thrilled about adding it.  What is bottom index?  Is it the last fully visible index or a partially visible one?  Note that since items in a table are currently all the same height, bottom index could be computed using getClientArea() and getItemHeight().

NOTE:  CAR, this code needs to be turned into a snippet.  Nicolas's case is reasonable and others may hit it.
Comment 4 Steve Northover CLA 2006-12-11 17:58:03 EST
WAIT!  I spoke too soon.  The code has yet to work for Nicolas.
Comment 5 Nicolas Richeton CLA 2006-12-12 06:00:31 EST
getBottomIndex should work the same way as getTopIndex. If it only return fully visible items, we can easily keep an item before the first and after the last one.

With this method, I only want to prevent calculation of visible item each time a new item appears. (With 100 items visible for example). Of course, this method would be useless if the table widget has to do the same calculation on each call, but I think that value is somehow calculated internaly by the table on redraw.

As I told before, I didn't test the code yet, I only looked at the calculation part that should give me the info I need. I will work on this snippet as soon as I can.

Another thing : my real problem is to handle Image creation and disposal in this table. With this method I still have to use an Image cache. Another way could be to listen for dispose events on TableItems to clear the corresponding Image.  But afaik there is not event fired when an item is cleared and the table is in virtual mode...   
Comment 6 Nicolas Richeton CLA 2006-12-17 04:38:48 EST
How can I do the same with a Tree ?
Comment 7 Boris Bokowski CLA 2007-02-14 13:29:04 EST
In bug 146799 comment #3, Grant wrote:
> SN, the issue here is that jface is calling Table.getTopIndex() from within the
> SetData callback, and is not getting the expected answer.  It uses this value
> to compute the set of currently visible items, and from this queries the model
> elements accordingly.

Could you please look at bug 146799 again and tell us if calling getTopIndex() from a SetData callback is supported now? (Your snippet on this bug does just that - it calls getTopIndex() from the callback.)
Comment 8 Eclipse Webmaster CLA 2019-09-06 15:29:56 EDT
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet.

If you have further information on the current state of the bug, please add it. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant.
Comment 9 Eclipse Webmaster CLA 2019-09-06 15:36:22 EDT
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet.

If you have further information on the current state of the bug, please add it. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant.