Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 98585 - [content assist] SWT.VIRTUAL style in the content-assist Table
Summary: [content assist] SWT.VIRTUAL style in the content-assist Table
Status: VERIFIED FIXED
Alias: None
Product: Platform
Classification: Eclipse Project
Component: Text (show other bugs)
Version: 3.1   Edit
Hardware: PC Windows XP
: P2 normal (vote)
Target Milestone: 3.1 RC3   Edit
Assignee: Tom Hofmann CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-06-06 16:38 EDT by Daniel Spiewak CLA
Modified: 2006-04-28 15:30 EDT (History)
8 users (show)

See Also:


Attachments
CompletionProposalPopup.diff (1.04 KB, patch)
2005-06-17 06:14 EDT, Tom Hofmann CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Daniel Spiewak CLA 2005-06-06 16:39:00 EDT
Please place an option in the preferences for Code Assist which allows the
developer to choose whether or not to have the content assist pop-up table use
the SWT.VIRTUAL style.  This is really a great feature to have on higher end
machines: It makes the pop-up come up very quickly.  However, on low end
machines (like the one I'm working on), it causes a very long time lag in moving
to a different set of completions.  A good test example is with an instance of
JFrame and trying to find a code assist option on one of the setters.  On my
Windows XP SP 2 machine, it takes between 5 and 10 seconds from when I enter the
's' character after the period until it actually finishes repopulating the code
assist.  I've been using Eclipse for a while, and I preferred the longer startup
delay to a longer repopulation delay.  If you could add a preference option to
change this, it would be appreciated.
Comment 1 Dani Megert CLA 2005-06-06 17:29:36 EDT
Please provide more details.
- build id
- more details about your machine
- eventually more detailed steps to repdocue the problem

see also:
http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/platform-text-home/development/bug-incomplete.htm
Comment 2 Daniel Spiewak CLA 2005-06-09 11:46:21 EDT
Eclipse 3.1 RC1 Win32.
Windows XP SP 2 with all current updates
Duel Processor 500 Mhtz
512 MB RAM
2 15 GB HD
JDK1.5 (possibly .1? not sure.  I know that sounds stupid but I'm really unsure
about that)

As for reproducing the error, it happens at every startup, all the time since M7
Comment 3 Dani Megert CLA 2005-06-09 12:13:41 EDT
>JDK1.5 (possibly .1? not sure.  I know that sounds stupid but I'm really unsure
>about that)
The link in comment 1 tells how to find out:
- VM information - if not sure start eclipse using -vmargs -showversion

>As for reproducing the error, it happens at every startup, all the time since M7
I don't see this. A step by step example that starts with a fresh workspace
could help.
Comment 4 Daniel Spiewak CLA 2005-06-09 14:42:51 EDT
Definately 1.5

I tried to get you a step by step example with a fresh workspace but it seems
that I can't reproduce the bug in a new workspace.  I'm sorry to take up your
time like this, but do you have any idea why my primary workspace would have
this problem, and a new workspace wouldn't?
Comment 5 Dani Megert CLA 2005-06-09 16:18:31 EDT
I think it's not new vs. existing but about how you've setup your existing
workspace, build path, number of depending plug-ins etc.
Comment 6 Daniel Spiewak CLA 2005-06-09 16:30:42 EDT
Could you elaborate please?  I'm not quite sure what I changed which could have
effected CTabItem.
Comment 7 Dani Megert CLA 2005-06-09 16:35:07 EDT
Did I mention CTabItem? I only said that what's in your workspace and how's it
setup (build path) will affect performance and hence the steps how we could
reproduce.
Comment 8 Daniel Spiewak CLA 2005-06-10 10:50:46 EDT
You know what, I'm terribly sorry.  I got this bug report confused with another
one I filed. :-)  Whoops.  Once again...

1) I start up Eclipse with a clean workspace
2) Switch to Java Perspective
3) Create new Java project "Test" (changed project compliance settings to 5.0)
4) Create new class file "Test.java" in the default package
5) Add javax.swing.* import
6) In the main method, add the code   JFrame frame = new JFrame();
7) type in frame.s (waiting for the content assist before typing 's')

It took eight seconds for the content assist to rebuild itself for the 's'
character.  To be honest, I've never had that problem on Linux or on Mac. 
Actually, I've never had it on Windows either before RC1.  Any thoughts?
Comment 9 Dani Megert CLA 2005-06-10 10:56:46 EDT
Is it just the first time? We now do much mor stuff lazy and hence the Java
model first needs to do some work. The SWT.VIRTUAL flag does not have that impact.
Comment 10 Daniel Spiewak CLA 2005-06-10 11:09:08 EDT
No actually, it happens every time the content assist comes up.  BTW, I used
JFrame just because it has a complex class hierarchy with numberous methods and
fields.  Thus, it takes longer to parse and it just shows the error better. 
Because of the slow speed of my machine though, I can see the error every time I
get the content assist.
Comment 11 Dani Megert CLA 2005-06-10 11:40:22 EDT
OK, I still don't see the 5 to 10 seconds but I see what you mean.
Comment 12 Tom Hofmann CLA 2005-06-10 11:46:10 EDT
Scenario on comment 8 works like a charm for me. My machine (Linux-GTK) is a
little faster, of course, but I do not see any flicker at all - it is much
smoother and faster than without using SWT.VIRTUAL for sure! Must be a
win32-only thing.
Comment 13 Dani Megert CLA 2005-06-14 10:03:52 EDT
1. have (JFrame imported):

  JFrame f;
  f.<caret>

2. Ctrl+Space and wait for the list
3. type 's'
==> on Mac and GTK its fast (sometimes very small flickering) while on WindowsXP
the list first clears (all white) for a second and then gets filled again.

Another test case, which is slow on the Mac, is to have S<caret> and then type 'A'.

SWT.VIRTUAL is not causing this. We remove the filtered proposals (due to typing
a character) using Table.remove(int,int) which seems to be terribly slow. Before
we used setRedraw(false/true) and always replaced the whole content.

Tom, please check with SWT what we should do here.

This is a must fix for 3.1.
Comment 14 Tom Hofmann CLA 2005-06-14 10:44:21 EDT
Steve, we currently try to 'optimize' the case where the list of items is
reduced. We compute the ranges of filtered items and use Table.remove(int,int).
Since the items are semi-sorted, we typically remove at most two or three ranges
when filtering. The rationale is that if the top n items are not filtered, they
are left untouched.

In the 'unoptimized' case, we simply set the table's item count and trigger the
virtual table to refill using Table.clearAll(). This seems to be acceptably fast
and smooth on GTK and Windows, even though all items are cleared.

Should we forget our optimization and just always use clearAll(), or might there
be a problem with the Table on Windows that is fixable for 3.1?

--

Code is in
org.eclipse.jface.text.contentassist.CompletionProposalPopup.setProposals()
Comment 15 Dani Megert CLA 2005-06-14 10:52:32 EDT
Dirk, this is a must fix. Do you approve as well?
Note: it's not yet clear whether we have to fix it on our side or whether SWT
can do something here.
Comment 16 Tom Hofmann CLA 2005-06-14 11:27:34 EDT
(In reply to comment #13)
> Another test case, which is slow on the Mac, is to have S<caret> and then type
> 'A'.

MacOSX seems to be different alltogether - no matter whether we use VIRTUAL or
not, range removal or clearAll, this case takes about 1-1.5 seconds on a G4
powerbook.

Just checked on Tobias' Windows box and the first scenario in comment 13 is
acceptably fast - while some scrollbar animations are noticable (probably due to
our multiple calls to remove(int,int)), it is nowhere near to the delay
noticable with Dani's machine.
Comment 17 Steve Northover CLA 2005-06-14 13:07:29 EDT
Ok, I'll look into it with Billy.  Stand by.
Comment 18 Dani Megert CLA 2005-06-15 15:54:35 EDT
Any update on this one?
Comment 19 Steve Northover CLA 2005-06-15 18:23:55 EDT
Didn't get time to look at it today.  Please make sure that the 'unoptimized' 
case is tested and ready to go on all platforms in case we don't get to it.

From memory, when you delete items, whether the Windows table is virtual or 
not, it redraws right away to show the change.  You can see this in the 
Windows Explorer when you delete files.  Is this what you are seeing?  If so, 
you could try doing a setRedraw(false)/setRedraw(true) around ALL of the range 
deletions.  If you try the setRedraw() code and it works for you, please let 
us try it out on the various platforms.

Let me know how you get on.
Comment 20 Steve Northover CLA 2005-06-15 18:25:16 EDT
The setRedraw() will guarantee that the whole table redraws but the user is 
expecting this when he types, no?  Whatever fix you decide, Billy and I will 
test it for you remotely.
Comment 21 Dani Megert CLA 2005-06-16 01:34:08 EDT
>the user is expecting this when he types, no? 
Mostly but lets say you see just 4 items in the list and the second one goes
away because you type some more characters it would look better if only that
item is removed instead of a full redraw of the table.

We have an 'unoptimized' version ready and tested on all Platforms using
redraw(true/false) - it basically feels like the 3.0 version plus the
SWT.VIRTUAL improvements. It makes the 1-2s white table go away on my WindowsXP
machine. Mac still flickers sometimes but that's not worse than before.

We would like to decide today and if possible have it in I20050616-1200 or
I20050616-1600.
Comment 22 Tom Hofmann CLA 2005-06-16 10:13:25 EDT
+1 for RC3 (signed Dirk Baeumer). Reviewed code on Tom's machine that is now
executed instead.
Comment 23 Dani Megert CLA 2005-06-16 12:50:20 EDT
This one went into I20050616-1200.
Comment 24 Steve Northover CLA 2005-06-16 13:27:48 EDT
Exactly which code went in?  The "hide flashing with setRedraw()"?  The "don't 
call Table.remove(int, int)"?  It'd help us to know what the code is doing 
when we are testing.
Comment 25 Dani Megert CLA 2005-06-16 14:32:27 EDT
>The "hide flashing with setRedraw()"?  The "don't 
>call Table.remove(int, int)"?
Both ;-)

The code is in project org.eclipse.jface.text:
org.eclipse.jface.text.contentassist.CompletionProposalPopup
Comment 26 Dani Megert CLA 2005-06-16 14:32:40 EDT
OLD code:
	private void setProposals(ICompletionProposal[] proposals, boolean
isFilteredSubset) {
		if (Helper.okToUse(fProposalTable)) {

			ICompletionProposal oldProposal= getSelectedProposal();
			if (oldProposal instanceof ICompletionProposalExtension2 && fViewer != null)
				((ICompletionProposalExtension2) oldProposal).unselected(fViewer);

			ICompletionProposal[] oldProposals= fFilteredProposals;
			fFilteredProposals= proposals;
			final int newLen= proposals.length;
			if (isFilteredSubset && oldProposals != null && fProposalTable.getItemCount()
== oldProposals.length) {
				final int oldLen= oldProposals.length;
				final int removedLen= oldLen - newLen;
				Assert.isTrue(removedLen >= 0 && newLen > 0);

				if (removedLen > 0) {
					int maxRanges= Math.min(oldLen / 2 + 1, removedLen);
					int[][] ranges= new int[maxRanges][2];
					int rangeIdx= 0;
					int[] range= null;
					ICompletionProposal next= proposals[0];
					int nextIdx= 0;
					for (int oldIdx= 0; oldIdx < oldLen; oldIdx++) {
						if (oldProposals[oldIdx] != next) {
							if (range == null || range[1] != oldIdx - 1)
								ranges[rangeIdx++]= range= new int[] { oldIdx, oldIdx };
							else
								range[1]= oldIdx;
						} else if (++nextIdx < newLen) {
							next= proposals[nextIdx];
						} else {
							if (oldIdx < oldLen - 1)
								ranges[rangeIdx++]= new int[] {oldIdx + 1, oldLen - 1};
							break;
						}
					}
					
					while (--rangeIdx >= 0) {
						range= ranges[rangeIdx];
						fProposalTable.remove(range[0], range[1]);
					}

				}
			} else {
				if (USE_VIRTUAL) {
					fProposalTable.setItemCount(newLen);
					fProposalTable.clearAll();
				} else {
					fProposalTable.setRedraw(false);
					fProposalTable.setItemCount(newLen);
					TableItem[] items= fProposalTable.getItems();
					for (int i= 0; i < items.length; i++) {
						TableItem item= items[i];
						ICompletionProposal proposal= proposals[i];
						item.setText(proposal.getDisplayString());
						item.setImage(proposal.getImage());
						item.setData(proposal);
					}
					fProposalTable.setRedraw(true);
				}
			}

			Point currentLocation= fProposalShell.getLocation();
			Point newLocation= getLocation();
			if ((newLocation.x < currentLocation.x && newLocation.y == currentLocation.y)
|| newLocation.y < currentLocation.y)
				fProposalShell.setLocation(newLocation);

			selectProposal(0, false);
		}
	}
Comment 27 Dani Megert CLA 2005-06-16 14:33:11 EDT
NEW (released) CODE:

	private void setProposals(ICompletionProposal[] proposals, boolean
isFilteredSubset) {
		if (Helper.okToUse(fProposalTable)) {

			ICompletionProposal oldProposal= getSelectedProposal();
			if (oldProposal instanceof ICompletionProposalExtension2 && fViewer != null)
				((ICompletionProposalExtension2) oldProposal).unselected(fViewer);

			fFilteredProposals= proposals;
			final int newLen= proposals.length;
			if (USE_VIRTUAL) {
				fProposalTable.setItemCount(newLen);
				fProposalTable.clearAll();
			} else {
				fProposalTable.setRedraw(false);
				fProposalTable.setItemCount(newLen);
				TableItem[] items= fProposalTable.getItems();
				for (int i= 0; i < items.length; i++) {
					TableItem item= items[i];
					ICompletionProposal proposal= proposals[i];
					item.setText(proposal.getDisplayString());
					item.setImage(proposal.getImage());
					item.setData(proposal);
				}
				fProposalTable.setRedraw(true);
			}

			Point currentLocation= fProposalShell.getLocation();
			Point newLocation= getLocation();
			if ((newLocation.x < currentLocation.x && newLocation.y == currentLocation.y)
|| newLocation.y < currentLocation.y)
				fProposalShell.setLocation(newLocation);

			selectProposal(0, false);
		}
	}
Comment 28 Dani Megert CLA 2005-06-16 15:56:08 EDT
Verified on WindowsXP.
Tom, please verify on Linux-GTK.

Could someone from SWT team verify on the MAC?

Should we file a different bug to investigate the remove(int,int)
Table.performance problem?
Comment 29 Billy Biggs CLA 2005-06-16 16:59:24 EDT
Seems good to me on the Mac using I20050616-1228.
Comment 30 Dani Megert CLA 2005-06-16 17:03:49 EDT
Addition to comment 28: I also used I20050616-1228 to verify.
Comment 31 Steve Northover CLA 2005-06-16 18:14:10 EDT
Yes, you could enter a bug about remove(int, int).

BB did you test Mochief?
Comment 32 Billy Biggs CLA 2005-06-16 19:00:04 EDT
Motif flashes a little worse with the new code, although I don't know if it's
bad enough to pull out the fix.  GG, any ideas on what's causing it?
Comment 33 Dani Megert CLA 2005-06-17 01:42:58 EDT
>Motif flashes a little worse with the new code, although I don't know if it's
>bad enough to pull out the fix.  GG, any ideas on what's causing it?
Compared to which build? If it's with 3.0 then SWT.VIRTUAL might also cause it.
If it's with a recent build then it's strange because we now almost use the 3.0
code again (except for SWT.VIRTUAL).
Comment 34 Tom Hofmann CLA 2005-06-17 03:11:47 EDT
(In reply to comment #28)
> Verified on WindowsXP.
> Tom, please verify on Linux-GTK.

Verified that there is no perceivable difference with I20050617-0010 on linux-gtk.
Comment 35 Tom Hofmann CLA 2005-06-17 05:53:45 EDT
On I20050617-0010-linux-motif, the flickering is stronger. SWT.VIRTUAL does not
seem to play well for motif - even setRedraw(on/off) does not help here. The
removal of the optimization also hurts a little since we didn't flicker if the
top-n proposals stayed the same.

Note that other operations than filtering do flicker either way on motif, as we
don't optimize there. The only thing we could do is not use VIRTUAL on motif,
trading pop-up speed against flickering.

Comment 36 Tom Hofmann CLA 2005-06-17 06:00:36 EDT
After discussion with Dani: not acceptable to have so much flickering on motif.
Comment 37 Tom Hofmann CLA 2005-06-17 06:14:17 EDT
Created attachment 23429 [details]
CompletionProposalPopup.diff

patch against CompletionProposalPopup.java

Disables use of the VIRTUAL table on motif.
Comment 38 Tom Hofmann CLA 2005-06-17 06:31:49 EDT
Verified on I20050616-1228-macosx that the (In reply to comment #31)
> Yes, you could enter a bug about remove(int, int).

filed bug 100552 to track this.
Comment 39 Dani Megert CLA 2005-06-17 07:32:19 EDT
As Tom said we have to fix the Motif case.

SWT: is it the right way for 3.1 to add platform dependent code to disable
virtual table on Motif or do you suggest a different alternative?
Comment 40 Grant Gayed CLA 2005-06-17 11:06:26 EDT
This is happening as a result of bug 90321.  Any time a horizontal or vertical 
scrollbar is hidden or shown there's a flash.  In the content assist case, 
since Table.itemCount() and Table.clearAll() are invoked on each keystroke, the 
scrollbar(s) are hidden and then reshown (when the SetData-->setText() dance is 
done) each time.  You'll notice that if you have a code assist window that does 
not need either scrollbar that the bad flash doesn't happen.

The only way for swt to fix this is to fix bug 90321, which was investigated in 
the M6 timeframe and could not be resolved.  It definitely won't be fixed for 
the 1200 build today.  So changing the content assist to not use VIRTUAL on 
motif seems like the thing to do here.
Comment 41 Dani Megert CLA 2005-06-17 11:44:40 EDT
OK, that's what we'll do for today. We can live with that for 3.1 unless you
tell us you have fix / better solution.
Comment 42 Steve Northover CLA 2005-06-17 12:03:37 EDT
I don't know about Platform.WS_MOTIF.equals(Platform.getWS()).  The SWT way to 
do it would be "motif".equals(SWT.getPlatform()).  It probably ends up being 
the same thing.  Pascal?
Comment 43 Douglas Pollock CLA 2005-06-17 14:32:23 EDT
Tested using I20050617-1227 on Linux Motif, admittedly on a fast machine (2.8
GHz w/ hyper-threading).  I saw no obvious flicker, and everything was quite
responsive.
Comment 44 Dani Megert CLA 2005-06-20 10:30:56 EDT
Marking as fixed. Pascal, can you reply to comment 42? Thanks.
Comment 45 Dani Megert CLA 2005-06-20 10:31:39 EDT
setting to verified, see comment 43.
Comment 46 Pascal Rapicault CLA 2006-04-28 15:30:07 EDT
On motif Platform.WS_MOTIF.equals(SWT.getPlatform()). However we don't share the same string object. That said, for the motif fragment to load the value of osgi.ws (which underlies Platform.getWS()) needs to be "motif" therefore, checking one or the other is the same.