Drawing text chunks (e.g. paras) in a text view with alternating background colours
Drawing text chunks (e.g. paras) in a text view with alternating background colours
- Subject: Drawing text chunks (e.g. paras) in a text view with alternating background colours
- From: Keith Blount <email@hidden>
- Date: Wed, 23 Sep 2009 14:09:30 -0700 (PDT)
Hi,
I have a text view that needs to draw different ranges of text with different background colours - although this isn’t as straightforward as it sounds as I’m not talking about text attributes but the actual text view background itself marking out different passages. Essentially I have an NSTextStorage subclass that represents multiple *other* text storage objects, so that the user can arbitrarily join text documents together and work on them as one, or work on them separately. My text view therefore has to indicate where one text storage begins and another ends when displaying the combined text storage object, so that the user can see the boundaries of each individual text storage component (each component is separated with one or two newlines, depending on the user’s settings). The way it does this is by drawing the background of the text view in alternating colours, a little like a massive variable-height table view, for different chunks of text.
Obviously, this has to do a minimum amount of drawing, checking the text on screen and only drawing the different coloured backgrounds as necessary.
It has a way of doing this already, but it’s really slow, and recent optimisation tests have shown this to be an issue. This is how I am currently handling this:
In my NSTextView subclass’s -drawViewBackgroundInRect: method, I get the range of characters in the current -visibleRect: using code similar to this:
http://www.cocoabuilder.com/archive/message/cocoa/2006/2/6/156183
This gives me the visible range of characters. My multiple text storage object returns the ranges of its constituent component text storages, so I can check the current visible range of characters against those to see if I need to draw the alternate colour (or more than one background colour if more than one component range is in the visible area).
To draw the background colours, ensuring that they fit perfectly behind my alternating ranges of text, I use NSLayoutManager’s -rectArrayForCharacterRange:... on the component ranges that are visible, then join the resultant rects (and expand to allow for the text container inset if necessary) and fill them with colour.
All of the above *works*, but in long texts, it can make typing slow. After all, -drawViewBackgroundInRect: gets called every time the user hits a key, meaning that in this scenario, every time the user types a character, the whole visible area has to get redrawn, and in so doing it calls on some slow-ish methods that do certain layout of their own, such as my -characerRangeForRect: method (in the link above), and NSLayoutManager’s -rectArrayForCharacterRange:...
So my question is, can anyone think of a better, more efficient way of solving this problem? Perhaps I am overcomplicating things. In case I haven’t explained clearly enough, what I am trying to do is very similar to, say, drawing alternating paragraphs in a text view with a different background colour (and again, I don’t mean as in NSBackgroundColorAttributeName, but a rectangle of background colour going from the left of the view to the right). Only in my case, each component may contain multiple paragraphs, of course.
Many thanks in advance for any ideas.
All the best,
Keith
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden