Community
Participate
Working Groups
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).
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).
Created attachment 180851 [details] Test Case
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.
(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!
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.
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.
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 ?
Back to Text
Created attachment 181474 [details] Picture showing discontinued line
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).
(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.
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 ?
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.
(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.
Is there an outlook on when this problem will be fixed? Thanks.
(In reply to comment #15) > Is there an outlook on when this problem will be fixed? Thanks. we can try for 3.8
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.