Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [platform-swt-dev] Problems with published StyledText API & documentation

Michael,
the default line styler that you use when you manage styles using the 
StyledText API maintains styles relative to the text vs. fixed to the 
range that was given in the style. This is in fact important information 
which we should add to the first article or to the JavaDoc. We mention the 
insert/delete text behavior briefly in the second article under 
"Implementing a LineStyleListener" but that is not nearly detailed enough.

In your text change scenarios the *text* between A and B will maintain the 
styles you originally set. 
  -in A<I<B the original style range will be split into A...I and 
(I+N)...B
  -when A=B there are no styles because the range is empty
  -if I...(I+N) overlaps the range from A...B in a replace operation the 
styles in the overlapped range are deleted. The second article does 
mention this, text replace == delete followed by insert where delete 
deletes the styles associated with the text.

Your guess regarding complexity of the style range update is correct. In 
the worst case, where text is inserted at offset 0 (or in front of the 
first style) all style start offsets are updated. This is a cheap 
operation, one simple addition for each style. In practice you just want 
to avoid adding unnecessary style ranges. For example you shouldn't add 
style ranges for a default, uncolored, style (e.g., black on white) 
because the widget background and foreground color can be used for this. 
Obviously the more styles you add the more work the widget does, not just 
when changing text but especially during rendering. 
The default line styler has optimizations to merge adjacent styles that 
are the same to avoid an explosion of styles as text is edited and styles 
are moved around and set via API.

About the JavaDoc
replaceStyleRanges:
The JavaDoc for the length argument doesn't make sense to me either. 
Simply sloppyness on our side. I fixed it although I'm wondering if you 
could actually leave the length argument 0 to add multiple styles without 
deleting any particular range. It would violate the spec but it may work. 
Maybe Lynne can comment (she is taking vacation this week).

setLineBackground:
The JavaDoc is useless. 
The way it works is that line background colors are again relative to the 
line text. An entire line is a line including its line delimiter at the 
end (this is defined by example in the first article under "Character, 
Line and Caret Offsets"). If you delete an entire line its line background 
color is deleted so that all other line colors remain the same, relative 
to the text. In the case were you join two lines by deleting a delimiter 
the top line takes precedence and the color of the bottom line is deleted. 
This may seem like a somewhat arbitrary decision but you will find that it 
is intuitive when you try it out.
In your example: 
AB\n            color X
CD\n            color Y
EF              color Z
If you end up with A\nF you either deleted B\nCD and then E or you deleted 
B and then CD\nE. The result is the same. The latter case is clear because 
you deleted the entire second line and line color Y with it. The first 
case is less clear because you didn't delete any line in its entirety.

setStyleRange:
At the top of the method it says 
"* Adds the specified style. The new style overwrites existing styles for the
 * specified range.  Existing style ranges are adjusted if they partially 
 * overlap with the new style, To clear an individual style, call setStyleRange 
 * with a StyleRange that has null attributes. "
The "specified range" is the range specified in the StyleRange so 
setStyleRange(2, 6, green) only sets the style for the text at offset 2, 
length 6 and leaves the one at offset 1 alone. I think this is pretty 
clear. However, whenever you have suggestions for JavaDoc improvements 
please submit them on the mailing list or enter a bug report. Your help is 
appreciated!

setStyleRanges vs. replaceStyleRanges:
setStyleRanges replaces "All styles" ("in the widget" could be added, like 
you suggest further down in your mail). replaceStyleRanges replaces styles 
"in the given range" only. setStyleRanges does not mention conflicting 
styles. It just slams all styles in the widget.
You could implement replaceStyleRanges by calling setStyleRange with 
styles that cover the entire replace range. You would have to create 
StyleRanges with null colors to delete existing style that have no 
replacement. This would not only be cumbersome but also inefficient. 
replaceStyleRanges was added in R2.0 to allow for performance 
improvements. It avoids a lot of duplicate array copy operations and 
screen update calculations that would occur if you looped over a 
setStyleRange call.
All style manipulating API only affect the range that you specified. All 
other styles will be left alone. It would be bad and unpredictable 
behavior if this were any different.
Good catch regarding the missing replaceStyleRanges in the list of API 
restricted to users of the default line styler.

In General
Have you considered implementing your own LineStyleListener instead of 
using API to update the styles in the StyledText widget? Styles that are 
derived from dynamic data suggest investigating a custom LineStyleListener 
implemention. Since you need to update styles based on syntax changes you 
may gain performance and save memory by not storing any styles but instead 
generating them whenever they are requested in the LineStyleListener. This 
decision depends on how cheap it is to generate styles for a given line 
based on your syntax tree.

Thanks for pointing out the unclear spec. I'll see if we can make the doc 
clearer. Feel free to enter bug reports if you see other problems with the 
doc and include your guesses or suggestions on what should be added if 
possible.

Knut





Michael Toomim <toomim@xxxxxxxxxxxxxxxx>
Sent by: platform-swt-dev-admin@xxxxxxxxxxx
08/25/02 08:57 PM
Please respond to platform-swt-dev

 
        To:     Lynne_Kues@xxxxxxx, knut_radloff@xxxxxxx
        cc:     platform-swt-dev <platform-swt-dev@xxxxxxxxxxx>
        Subject:        [platform-swt-dev] Problems with published StyledText API & documentation

SWT devlopers:

I'm implementing an Eclipse text editor plugin that derives style 
information from a dynamically-updated syntax tree rather than a lexer. 
  In the course of development, I've run across some issues with the 
published StyledText API, where important aspects of the widget's 
behavior appear to have been omitted.

A general high-level problem is that I can't find any API specification 
describing how the StyledText widget's styling state changes over time. 
  This is important, since I want to update the StyledText widget 
incrementally as my syntax tree changes.  I've searched the 
"swimming"-themed online articles (feet wet, deep end) and the javadocs, 
and came up with the following list if specific specification holes. 
Before I dig into the code, I thought I'd share it with you guys.  If 
these are, indeed, significant omittions, maybe it could get fixed for 
the future?

- Un-answered questions:

If I set a styled range from offset A to offset B in the widget, I know 
that the displayed characters from A to B will have the corresponding 
style immediately after I call setStyleRange().  But what styles will be 
displayed after the text buffer changes?  Where, for instance, will the 
existing style be displayed...

    - If I insert/delete N characters at I<A?  I=A?  A<I<B?  I=B? A<B<I?
    - If A=B, and I insert I characters at I=A=B?
    - If I replace characters in a range that overlaps A and/or B?

If the StyledText widget has to do processing to update ranges after a 
text change, how long does that processing take?  O(number of ranges), 
maybe?  (Hopefully not.)

- Specific parts of the javadocs that I didn't understand:

replaceStyleRanges(): says "use 0 [for the length parameter] to insert 
text".  What does this mean?  How can you insert text with this method 
at all?  I thought this method replaced *styles*, not text...  This 
doesn't make any sense to me.

setLineBackground(): says "During text changes, when entire lines are 
inserted or removed, the line background colors that are associated with 
the lines after the change will "move" with their respective text. For 
all other text changes, line background colors will remain unchanged." 
    This description is a little vague...  What defines an "entire line"?

    - Is it "a line of characters and the newline at the end"?
    - Is it "a line of characters and the newline at the beginning"?
    - "A newline"?

What about the following situation:  The text buffer starts out as 
"AB\nCD\nEF".  Each line has a different color (X, Y, and Z).  Now, text 
is deleted to make the buffer "A\nF".  What colors are all the lines?

setStyleRange():  The javadoc says: "Overwrites the old style in the 
given range."  What is the definition of "style in the given range"? 
For instance, if I set the range (1,4) to blue, and then call 
setStyleRange(2, 6, green), does it result in (1,2)=blue and 
(2,6)=green, or just (2,6)=green?  Does it overwrite all styles that 
intersect with the new style, or just the style for characters covered 
by the new range?

In general, how does the StyledText widget maintain style information?

What's the difference between setStyleRanges(StyleRange[]) and 
replaceStyleRanges(from, to, StyleRange[])?  Both of them claim to 
replace existing StyleRanges that conflict with the new StyleRanges.  On 
the surface, the only difference appears to be that replaceStyleRanges() 
lets you specifically say what range of styles should be erased, whereas 
setStyleRanges makes that information implicit (anything covering the 
ranges will be replaced).  But this doesn't make sense, because you 
could effectively implement replaceStyleRanges() with setStyleRanges() 
then, by constructing null StyleRange objects for all regions that are 
specified in from and to, but aren't covered by the StyledRange[] 
argument to replaceStyleRanges().  Is this really a duplication in API?

Here are some slightly more pointed questions:

    "setStyleRanges(StyleRange[] ranges)

        Sets styles to be used for rendering the widget content. All
        styles will be replaced with the given set of styles."

Does this mean "all styles in the widget", or just "all styles that are 
lying in the way of the ranges being set"?  Which ranges, precisely, 
will go away?

    "public void replaceStyleRanges(int start,
                                int length,
                                StyleRange[] ranges)

        Replaces the styles in the given range with new styles. This
        method effectively deletes the styles in the given range and then
        adds the the new styles."

I have the same question here as I did for setStyleRange(StyleRange). 
If `start' or `end' overlap an existing StyleRange region, does this 
method remove JUST the overlapping part of the StyleRange, or does it 
remove the whole range even if only part of it overlaps?

Also, at the top of the StyledWidget javadocs, it says:

"The following StyledText API is not supported if you have defined a 
LineStyleListener:

     * getStyleRangeAtOffset(int)
     * getStyleRanges()
     * setStyleRange(StyleRange)
     * setStyleRanges(StyleRange[])"

This leaves out replaceStyleRanges(), which can't be used with 
LineStyleListeners either.


Thanks for your time,

Michael

_______________________________________________
platform-swt-dev mailing list
platform-swt-dev@xxxxxxxxxxx
http://dev.eclipse.org/mailman/listinfo/platform-swt-dev





Back to the top