Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 326644

Summary: StyledText selection erases painted characters behind last character
Product: [Eclipse Project] Platform Reporter: Dani Megert <daniel_megert>
Component: SWTAssignee: Platform-SWT-Inbox <platform-swt-inbox>
Status: CLOSED WONTFIX QA Contact:
Severity: normal    
Priority: P3 CC: deepakazad, eclipse.felipe, shanec, Silenio_Quarti
Version: 3.3   
Target Milestone: ---   
Hardware: All   
OS: All   
Whiteboard: stalebug
Attachments:
Description Flags
Test Case
none
"fixed" testcase
none
Picture showing discontinued line none

Description Dani Megert CLA 2010-09-30 04:23:05 EDT
The org.eclipse.jface.text.WhitespaceCharacterPainter uses a PaintListener to paint line delimiter characters behind the last real character.

This works in general but there is one case where this fails: if StyledText is created *without* SWT.FULL_SELECTION then the selection cuts off the painted characters even though paint event and the GC aren't clipped.

Since it works with SWT.FULL_SELECTION I would expect this to work in the other case too.

Test Case:
- enable 'Show Withspace characters' on the General > Text Editors pref page
- compare two version of a text file in the compare editor
  ==> whitespace characters are shown
- make a selection that spawns several lines
==> painted whitespace characters are partially erased (cut to the length of the selection).
Comment 1 Felipe Heidrich CLA 2010-10-13 13:48:21 EDT
I see this problem on Eclipse, windows and linux.

But I could not reproduce it on a simple test case:

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

public class Bug {
public static void main(String[] args) {
	Display display= new Display();
    Shell shell= new Shell(display);
    shell.setLayout(new FillLayout());
    final StyledText text= new StyledText(shell, SWT.V_SCROLL | SWT.H_SCROLL);
    String contents= "line0\nline1\nline2";
    text.setText(contents);
    text.setFont(new Font(display, "Courier New", 11, SWT.NORMAL));
    text.addListener(SWT.Paint, new Listener() {
		public void handleEvent(Event event) {
			int lineCount = text.getLineCount();
			GC gc = event.gc;
			int alpha= gc.getAlpha();
			gc.setAlpha(100);
			for (int i = 0; i < lineCount; i++) {
				int startOffset = text.getOffsetAtLine(i);
				int length = text.getLine(i).length();
				Point pt = text.getLocationAtOffset(startOffset + length);
				event.gc.drawString("\u00a4\u00b6", pt.x, pt.y, true);
			}
			gc.setAlpha(alpha);
		}
	});
    shell.open();
    while (!shell.isDisposed()) {
        if (!display.readAndDispatch())
            display.sleep();
    }
    display.dispose();
}
}


--*-*-*-*--*

What is it that I'm missing ? Is there other paint listener running before or after WhitespaceCharacterPainter ? 

Since the problem happens on linux and windows it indicates the bug in either in StyledText or in the applicaton (in other words, TextLayout is probably not at fault in this case).
Comment 2 Dani Megert CLA 2010-10-14 02:52:55 EDT
Created attachment 180851 [details]
Test Case
Comment 3 Felipe Heidrich CLA 2010-10-14 10:25:30 EDT
Back to JFace text.
WhitespaceCharacterPainter is drawing with white foreground when the end of line is selected. When the widget is full selection the code is okay because white foreground shows fine on blue background, when full selection is not set the code draws white on white.
Comment 4 Dani Megert CLA 2010-10-14 10:27:22 EDT
(In reply to comment #3)
> Back to JFace text.
> WhitespaceCharacterPainter is drawing with white foreground when the end of
> line is selected. When the widget is full selection the code is okay because
> white foreground shows fine on blue background, when full selection is not set
> the code draws white on white.
Oops!
Comment 5 Dani Megert CLA 2010-10-14 10:55:32 EDT
OK, I have fixed that but there's another problem which you can also easily see in your snippet: it "erases" the first delimiter character because StyledText draws the selection larger than there are visible characters. And this is in the middle of that first character.
Comment 6 Dani Megert CLA 2010-10-15 03:06:36 EDT
Though we'd prefer not to set any background (to let other painters do this if desired) I tried that approach as well, but it doesn't work because the drawn background does not entirely fill the background behind line delimiter characters: there's some white shining through from the white widget background.
Comment 7 Felipe Heidrich CLA 2010-10-15 11:15:34 EDT
Created attachment 180969 [details]
"fixed" testcase

Try this test case (modifed from the one you posted).

I tested on windows xp,gtk, cocoa. Looks good to me.

Is that a good solution for you too ?
Would you like me to prepare a patch for WhitespaceCharacterPainter or will you integrate the changes yourself ?
Comment 8 Felipe Heidrich CLA 2010-10-18 12:08:17 EDT
Back to Text
Comment 9 Dani Megert CLA 2010-10-22 04:06:04 EDT
Created attachment 181474 [details]
Picture showing discontinued line
Comment 10 Dani Megert CLA 2010-10-22 04:12:01 EDT
Thanks Félipé!

> Is that a good solution for you too ?
See comment 6: we'd prefer not to touch the background because other painters want to draw their own stuff too, e.g. in case of compare you can see that one would no longer see the full line (see attachment 181474 [details]) and it looks a bit like cheese, especially if the compare editor shows many changes/lines.

What about a flag that allows me to tell StyledText not to bleed the selection over the last real character? That way, the line delimiters would be fully visible (though on the default background, but that's acceptable).
Comment 11 Felipe Heidrich CLA 2010-10-22 12:17:26 EDT
(In reply to comment #10)
> What about a flag that allows me to tell StyledText not to bleed the selection
> over the last real character? That way, the line delimiters would be fully
> visible (though on the default background, but that's acceptable).

I suppose we can do that.

Silenio, StyledText has two modes to draw selection on line delimiters:
NORMAL - only draws 1/3 of lineHeight to indicate \r\n is selected
FULL - fills the entire reminder of the client area width.

To fix this problem as suggested by Dani we will need to add a third mode, in which nothing is draw to indicate selection on line delimiters.

This will be a new style flag or method to StyledText. Nothing is need on TextLayout. It would actually be easy to implement.
Comment 12 Felipe Heidrich CLA 2010-11-05 12:01:21 EDT
I talked with Silenio, this is what we come up with.

Right now TextLayout has drawFlags, right now it supports:
SWT.FULL_SELECTION - selection extension to fill the entire client area.
SWT.SWT.DELIMITER_SELECTION - selection extension to fill just the delimiter size.

(it also has a SWT.LAST_LINE_SELECTION but it is something separeted, it indicates TextLayout to draw the selection extension for the last line).

Unfortunatelly if drawFlags is zero, then the SWT.SWT.DELIMITER_SELECTION behaviour is used.

We would have to change that behaviour, so that when drawFlags is zero no selection extension is drawn. I think this change is okay.

After that, we would be able to add new methods to StyledText:

setSelectionMode (), getSelectionMode ()
takes SWT.FULL_SELECTION, SWT.DELIMITER_SELECTION, and SWT.NONE
SWT.FULL_SELECTION is used when the control is created with SWT.FULL_SELECTION 
SWT.DELIMITER_SELECTION is used when the control is created without SWT.FULL_SELECTION (backwards compatiple)
SWT.NONE - has to be set using setSelectionMode (), and no selection extension would be drawn in this mode.

Makes sense ?
Comment 13 Dani Megert CLA 2010-11-05 13:17:12 EDT
Sounds good in general. One question:

>SWT.SWT.DELIMITER_SELECTION - selection extension to fill just the delimiter

That's not what I see. I see that e.g. for \r\n it selects about 3/4 of \r only.
Comment 14 Felipe Heidrich CLA 2010-11-05 13:56:48 EDT
(In reply to comment #13)
> That's not what I see. I see that e.g. for \r\n it selects about 3/4 of \r
> only.

Is it actually 1/3 of lineHeight ;-)
We have being cheating it for years, nobody noticed.
Basically it is not reliable to measure "\r\n" (some fonts just return 0), and using 1/3 is just faster too.
Comment 15 Shane Cartledge CLA 2011-06-02 14:10:28 EDT
Is there an outlook on when this problem will be fixed? Thanks.
Comment 16 Felipe Heidrich CLA 2011-06-03 10:09:26 EDT
(In reply to comment #15)
> Is there an outlook on when this problem will be fixed? Thanks.

we can try for 3.8
Comment 17 Lars Vogel CLA 2019-11-14 03:52:47 EST
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.

If the bug is still relevant, please remove the "stalebug" whiteboard tag.