Bug 115432 - [Graphics] TextLayout.setIndent not supporting "out-denting"
Summary: [Graphics] TextLayout.setIndent not supporting "out-denting"
Status: RESOLVED FIXED
Alias: None
Product: Platform
Classification: Eclipse Project
Component: SWT (show other bugs)
Version: 3.2   Edit
Hardware: Other All
: P3 normal (vote)
Target Milestone: 3.6 M4   Edit
Assignee: Felipe Heidrich CLA
QA Contact: Felipe Heidrich CLA
URL:
Whiteboard:
Keywords:
: 159277 (view as bug list)
Depends on:
Blocks: 288767
  Show dependency tree
 
Reported: 2005-11-07 23:55 EST by Phil Stone CLA
Modified: 2009-11-02 10:30 EST (History)
8 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Phil Stone CLA 2005-11-07 23:55:36 EST
Code snippet 203 has the following as part of its example  
code.  The "setIndent" call, new to 3.2M3, is rounding down negative  
numbers to zero.  It should take negative numbers to indicate that  
successive lines, those after the first, will be indented by the   
absolute value of the setIndent parameter.  
  
In otherwords, a negative indent is an outdent.  (But, to keep the rest of  
the API working, it should be interpreted as I've suggested here, successive  
lines are indented by a positive amount equal to the amount less than zero  
on the setIndent API.)  
  
PLEASE fix this now, before you have client code dependent on it and you  
loose the ability to do "outdents."  
  
The following is the code fragment from snippet203, changed to a  
negative indent, that should NOT be treated as a zero...  
  
AS IT STANDS TODAY YOU CANNOT SUPPORT POETRY, ONLY PROSE!!!!!  
  
                TextLayout layout = new TextLayout(display);   
                layout.setText(texts[i]);   
                layout.setIndent(-30);   // THE CHANGE, BROKEN!!!!!!  
                layout.setJustify(true);   
                layout.setAlignment(alignments[i]);                
                layouts[i] = layout;
Comment 1 Steve Northover CLA 2005-11-09 15:43:54 EST
I like poetry.  Is there another way to get what Phil wants?
Comment 2 Phil Stone CLA 2005-11-09 17:13:26 EST
I've been thinking about how to use TextLayout for the past 
couple days and can see another way to put this in the interface that 
would be more general, and easier to use, at least in the cases that 
I can immediately forsee... 
 
We're trying to drive the indent used by TextLayout after an AUTOMATIC 
line-wrap.  Where should these unplanned lines start?  At 0?  Or indented? 
 
The answer to the question should be another attribute, say "setWrapIndent." 
 
Whenever an auto-wrap happens, use that indent, not 0, though 0 is the 
natural default, the one you are using now. 
 
NOTE, that the regular indent, that you just added to the API in 3.2M3, 
is for the first line and any other lines that are caused by NEW-LINEs in 
the text itself.  This is important so both indent values can be used 
down across a string of text.   
 
By having 2 values it automatically allows a poem to be indented from nearby 
prose without having to shift the alignment of the entire TextLayout.  This is 
helpful in cases where a long list of TextLayouts are used together, the normal 
case. 
   
Sorry for not suggesting this in the original bug, it has taken a couple days   
to think through using the setIndent itself.  (Which is otherwise very nice.) 
   
So, the fragment would become...  
 
String poem = "The rain in Spain\nFalls mainly in the plain."; 
  
TextLayout layout = new TextLayout(display);     
layout.setText(poem);     
layout.setIndent(30);  
layout.setWrapIndent(60);  // Alternative 
 
The start of the first line of the poem always aligns with the start of the 
second line of the poem, because both use the regular indent.  The NEW-LINE is 
what triggers a wrap back to the regular indent.   
 
Which, of course, might be set to zero depending on other issues of formatting.   
 
Any wrapping needed for the lines to fit are indented by the WrapIndent, so 
these lines don't hide the starting lines of the poem. 
 
Phil   
   
   
Comment 3 Travis Breaux CLA 2006-09-29 16:54:02 EDT
*** Bug 159277 has been marked as a duplicate of this bug. ***
Comment 4 Markus Keller CLA 2008-04-04 06:38:55 EDT
See also bug 56342 (requests margins inside a StyledText).
Comment 5 Felipe Heidrich CLA 2009-02-24 16:57:07 EST
Okay, you proposed to options:

Option 1) setLineIndent (negative value)
Option 2) setWrapIndent (int)

Option 1 can be implememted on win32, gtk, motif, and cocoa
Option 2 can be implemented on win32, motif, and cocoa

Carbon has no support for it.

I believe that with Option 1 you can do everything you need (you will have change the x location of the layout in some cases but that is easy). 
The problem with Option 2 is that isn't natevily supported by Pango, so it makes much more dificult to implement it the GTK port.
Comment 6 Markus Keller CLA 2009-02-25 07:02:19 EST
What about bullet lists? When they wrap, there are 2 valid strategies to indent continuation lines:
a) indent like the bullet (i.e. line indent)
b) indent like the bullet line text (i.e. line indent + bullet glyph width)

I would prefer b) in most cases, but Option 1 would have to choose one.
Comment 7 Felipe Heidrich CLA 2009-02-25 10:54:52 EST
(In reply to comment #6)
> I would prefer b) in most cases, but Option 1 would have to choose one.
You meant(?):
>I would prefer b) in most cases, but Option 1 would have to choose a).


I think you can have b) with Option 1.
You can control the indent of the first line of the paragraph by setting the glyph width of the bullet (basically glyph width = bullet width + line indent. Yeah, you would have to custom draw the bullet to draw only in the bullet width portion of it).
All the other lines you can control with setLineIndent(negativeNumber).

For StyledText, I know it would need more API, maybe something like setLineMargin().
Comment 8 Markus Keller CLA 2009-02-25 13:23:45 EST
> > I would prefer b) in most cases, but Option 1 would have to choose one.
> You meant(?):
> >I would prefer b) in most cases, but Option 1 would have to choose a).

No, I really meant that with Option 1, TextLayout needs to specify one of a) or b) as default behavior.

Some ASCII-art to illustrate a) and b) ('.' is the dot, ']' marks line indent):
a) ]
     . aa aaaaa a a aaaa
    aaaaa aaaaaa (wrapped line indented like bullet)
b) ]
     . bb bbbbb b b bbbb
       bbbbb bbbbbb (wrapped line indented like text after bullet of first line)

When setLineIndent (negative value) implements a), I as a client could probably get b) by setting the glyph width to 0, increasing the indent by the glyph width, and drawing the bullet outside the actual area reserved for the bullet (in the indent area).

But if the default is b), then I don't know how I could implement a). The problem is that both a) and b) have serious drawbacks:
a) would allow full flexibility but forces every client to apply hacks to get the more desirable b).
b) would be what I'd say should be the default, but I don't see how a client could hack a) with this.
Comment 9 Felipe Heidrich CLA 2009-08-19 15:59:29 EDT
Your bug has been moved to triage, visit http://www.eclipse.org/swt/triage.php for more info.
Comment 10 Susan McCourt CLA 2009-10-23 12:18:00 EDT
Bug 288767 only depends on the ability to achieve setLineWrapIndent(int value).  

This is affecting the usability of the error dialog.  Clients are asking us to
wrap the error dialog text, but due to the nested nature of the
status/exception traces, we need wrapping to respect previous indention.
Comment 11 Felipe Heidrich CLA 2009-10-29 15:36:40 EDT
Fixed in HEAD > 20091029 (BUT NOT IN M3)

See:
TextLayout#setWrapIndent(int)
TextLayout#getWrapIndent(int)
StyledText#setWrapIndent(int)
StyledText#getWrapIndent(int)
StyledText#setLineWrapIndent(int, int, int)
StyledText#getLineWrapIndent(int)
LineStyleEvent#wrapIndent

Susan, you should be able to fix your problem with:

styledText.setLineIndent(indent);          //affects the first line
styledText.setLineWrapIndent(indent);      //affects all other lines


Markus, you should be able to fix your problem with:

styledText.setLineBullet(2, 4, bullet0);
styledText.setLineWrapIndent(2, 4, bullet0.style.metrics.width);

(I'll post a snippet later on)

Note: I was able to implement this feature on all platforms but carbon.
tested on win32, gtk, carbon, wpf, and motif.
Comment 13 Jörg Thönnes CLA 2009-11-02 07:20:35 EST
Will there be a backport for Eclipse 3.5 SR2?
Comment 14 Krzysztof Daniel CLA 2009-11-02 07:45:58 EST
It is API change. I do not think it is possible to backport it.
Comment 15 Markus Keller CLA 2009-11-02 09:04:50 EST
Looks good, but there's an API tooling error in HEAD of TextLayout.java:
Invalid @since 3.2 tag on getWrapIndent(); expecting @since 3.6
Comment 16 Felipe Heidrich CLA 2009-11-02 10:30:30 EST
(In reply to comment #15)
> Looks good, but there's an API tooling error in HEAD of TextLayout.java:
> Invalid @since 3.2 tag on getWrapIndent(); expecting @since 3.6

thank you, fixed.