RichTextCtrl blues

Hi all,

For the past year, I've been working on a major re-write of my application
to switch from the StyledTextCtrl to the RichTextCtrl. I've resolved a lot
of issues, large and small, and am generally really pleased with the
results. Except that there are a couple of problems that I have to resolve
before I can do a release, and I'm stuck. I'd appreciate any guidance you
can offer.

I did most of my development with the wxPython 2.8.x series. I have almost
everything working perfectly. I can produce long documents with embedded
images and fancy formatting that look great and export to Rich Text Format.
(During stress testing, I transcribed The Matrix, including about 100 screen
shots, producing an 18MB RTF document.) The last obstacle I've run across,
during final pre-release testing, is that if I try to change the formatting
on a large selection of text, I run into problems. On Windows, the Windows
GDI handles in use rapidly increase, and when they hit 10,000, my program
slows and then crashes. On OS X, the equivalent large selection format
change just crashes. A bit of investigation shows that this is due to an
issue in wxWidgets, which I have reported. But they've moved on from 2.8 to
2.9, so the issue won't (I don't think) receive much attention.

So yesterday, I decided to look into the latest wxPython, 2.9.2.4, to see if
that fixes the problem. My initial tests suggest that the GDI issue has
been resolved, that the RichTextCtrl doesn't leak GDI resources on Windows
any more. Yay! Problem solved, right? Not so fast.

1) I'm seeing odd formatting problems in the RichTextCtrl under 2.9.2.4.
I've attached a sample app, RTC_2_9_2_4_Problem.py, along with two images
that show the printout of that app under different wxPython versions.

RTC_Problem_2.8.12.1.jpg shows the sample app printout under wxPython
2.8.12.1, and everything works exactly as I would expect it to. All of my
section headings and text are formatted correctly.

As RTC_Problem_2.9.2.4.jpg shows, lines with a left indent wrap unexpectedly
when they are too short to need to wrap. This messes up the section headers
in my reports and causes the types of documents that my program is used for
(transcription of media files) to look like crap more often than not.

I noticed that wxPython 2.9.2.4 was a quick release claiming to fix indent
problems, so I wondered if this might be a variation on the theme that
wasn't caught before. I'm hoping against hope that this issue is something
on the wxPython level that can be fixed quickly and easily. I'm not
optimistic about this possibility, but I thought I'd at least ask. If not,
let me know and I'll see if I can recreate the problem in a wxWidget/C
example.

2) I also notice that with 2.9.2.4, the RichTextPrinting and
RichTextPrintout objects no longer exist in the wx.richtext module. Is
there a standard replacement for these objects that allows printing of
RichTextCtrl contents that I'm just not seeing?

3) Finally, although the GDI issue has been solved on Windows, I see that
large numbers of formatting changes (somewhere between 4681 characters and
4752 characters, given my particular application, which admittedly has some
unusual formatting conditions that leave me changing formatting one
character at a time) still crash the program. I will pursue this issue more
systematically once I've sorted out the other two issue.

Thanks in advance for your thoughts.

David K. Woods, Ph.D.
Researcher, Transana Lead Developer
Wisconsin Center for Education Research
University of Wisconsin, Madison
http://www.transana.org

RTC_Problem_2.8.12.1.jpg

RTC_Problem_2.9.2.4.jpg

RTC_2_9_2_4_Problem.py (11.9 KB)

Hi all,

...

1) I'm seeing odd formatting problems in the RichTextCtrl under 2.9.2.4.
I've attached a sample app, RTC_2_9_2_4_Problem.py, along with two images
that show the printout of that app under different wxPython versions.

RTC_Problem_2.8.12.1.jpg shows the sample app printout under wxPython
2.8.12.1, and everything works exactly as I would expect it to. All of my
section headings and text are formatted correctly.

As RTC_Problem_2.9.2.4.jpg shows, lines with a left indent wrap unexpectedly
when they are too short to need to wrap. This messes up the section headers
in my reports and causes the types of documents that my program is used for
(transcription of media files) to look like crap more often than not.

...

2) I also notice that with 2.9.2.4, the RichTextPrinting and
RichTextPrintout objects no longer exist in the wx.richtext module. Is
there a standard replacement for these objects that allows printing of
RichTextCtrl contents that I'm just not seeing?

...

Thanks in advance for your thoughts.

David K. Woods, Ph.D.
Researcher, Transana Lead Developer
Wisconsin Center for Education Research
University of Wisconsin, Madison
http://www.transana.org

Unfortunately, I don't have many experiences with the richtext module,
hopefully someone more knowledgeable will be able to help.
Just a suggestion for a problem searching - on my system (win XP) your
code seem to display the page correctly in wx 2.9.1.1 (msw-unicode)
(visually the same as 2.8);
for 2.9.2.4 I can confirm the buggy wrapping you describe.
There is a missing printing interface in both 2.9 versions in question.

regards,
   vbr

···

2011/9/27 David Woods <dwoods@wcer.wisc.edu>:

Hi all,

For the past year, I've been working on a major re-write of my application
to switch from the StyledTextCtrl to the RichTextCtrl. I've resolved a lot
of issues, large and small, and am generally really pleased with the
results. Except that there are a couple of problems that I have to resolve
before I can do a release, and I'm stuck. I'd appreciate any guidance you
can offer.

I did most of my development with the wxPython 2.8.x series. I have almost
everything working perfectly. I can produce long documents with embedded
images and fancy formatting that look great and export to Rich Text Format.
(During stress testing, I transcribed The Matrix, including about 100 screen
shots, producing an 18MB RTF document.) The last obstacle I've run across,
during final pre-release testing, is that if I try to change the formatting
on a large selection of text, I run into problems. On Windows, the Windows
GDI handles in use rapidly increase, and when they hit 10,000, my program
slows and then crashes. On OS X, the equivalent large selection format
change just crashes. A bit of investigation shows that this is due to an
issue in wxWidgets, which I have reported. But they've moved on from 2.8 to
2.9, so the issue won't (I don't think) receive much attention.

So yesterday, I decided to look into the latest wxPython, 2.9.2.4, to see if
that fixes the problem. My initial tests suggest that the GDI issue has
been resolved, that the RichTextCtrl doesn't leak GDI resources on Windows
any more. Yay! Problem solved, right? Not so fast.

1) I'm seeing odd formatting problems in the RichTextCtrl under 2.9.2.4.
I've attached a sample app, RTC_2_9_2_4_Problem.py, along with two images
that show the printout of that app under different wxPython versions.

RTC_Problem_2.8.12.1.jpg shows the sample app printout under wxPython
2.8.12.1, and everything works exactly as I would expect it to. All of my
section headings and text are formatted correctly.

As RTC_Problem_2.9.2.4.jpg shows, lines with a left indent wrap unexpectedly
when they are too short to need to wrap. This messes up the section headers
in my reports and causes the types of documents that my program is used for
(transcription of media files) to look like crap more often than not.

I noticed that wxPython 2.9.2.4 was a quick release claiming to fix indent
problems, so I wondered if this might be a variation on the theme that
wasn't caught before. I'm hoping against hope that this issue is something
on the wxPython level that can be fixed quickly and easily. I'm not
optimistic about this possibility, but I thought I'd at least ask. If not,
let me know and I'll see if I can recreate the problem in a wxWidget/C
example.

That is very weird. I have no idea what's going on however so I think you'll need to report this to Julian to get any help with it.

2) I also notice that with 2.9.2.4, the RichTextPrinting and
RichTextPrintout objects no longer exist in the wx.richtext module. Is
there a standard replacement for these objects that allows printing of
RichTextCtrl contents that I'm just not seeing?

The code is there in the 2.9 source tree, but somehow it was never included in the richtext module. Sorry about that. It will be in the next release.

···

On 9/27/11 8:53 AM, David Woods wrote:

3) Finally, although the GDI issue has been solved on Windows, I see that
large numbers of formatting changes (somewhere between 4681 characters and
4752 characters, given my particular application, which admittedly has some
unusual formatting conditions that leave me changing formatting one
character at a time) still crash the program. I will pursue this issue more
systematically once I've sorted out the other two issue.

--
Robin Dunn
Software Craftsman

Just a thought to rework your older code with the older widget, how about reformatting your large selected content by breaking the selection down into smaller selections. Perhaps use an iterator, or generator.

def segmentReformat(self, rtwidget, newformat):

‘’‘Reformat only selected content - in small chuncks’‘’

rtwidget.Freeze(True)

initialSelection = rtwidget.GetSelection()

initialLength = initialSelection[1] - initialSelection[0]

remainingSelection = initialLength

mySegSize = 2000 # a magic number randomly picked for this demo

finger = 0

while remainingSelection > 0:

thisSegSize = max( min( remainingSelection, mySegSize), 0) # to avoid miscalculations resulting below zero

subSelection = ( finger, finger+thisSegSize)

rtwidget.SetSelection( finger, finger+thisSegSize)

self.Reformat( rtwdiget, newformat) # whatever method now reformats the content

finger = finger + thisSegSize + 1

remainingSelection = remainingSelection - thisSegSize

yield subSelection

wx.Yield()

reselect original selected text

rtwidget.SetSelection( *initalSelection )

rtwidget.Thaw()

Other ideas: for segmenting large selections:

http://wiki.wxpython.org/LongRunningTasks

Other things to consider.

The segmentation of the content-selection reminded me of the old DC device context trick used in printing images on old printers using something called “banding”. Which brought to mind that when you reformat text, sometimes you need to let the widget have enough time to recalculate it’s printing/display properties, as this is an event driven package and there are not guarentees of the order of processing. I have no idea if RichTextCtrl is reformatting your content but not recalculating each content objects properties (ie margins, etc) sooner then your reformatting method, although I seriously doubt that’s the issue.

···

On Tue, Sep 27, 2011 at 11:53 AM, David Woods dwoods@wcer.wisc.edu wrote:

Hi all,

… The last obstacle I’ve run across,
during final pre-release testing, is that if I try to change the formatting

on a large selection of text, I run into problems. On Windows, the Windows
GDI handles in use rapidly increase, and when they hit 10,000, my program
slows and then crashes. On OS X, the equivalent large selection format

change just crashes. A bit of investigation shows that this is due to an
issue in wxWidgets, …David K. Woods, Ph.D.

        Hi all,
        
        ... The last obstacle I've run across,
        during final pre-release testing, is that if I try to change
        the formatting
        on a large selection of text, I run into problems. On
        Windows, the Windows
        GDI handles in use rapidly increase, and when they hit 10,000,
        my program
        slows and then crashes. On OS X, the equivalent large
        selection format
        change just crashes. A bit of investigation shows that this
        is due to an
        issue in wxWidgets, ...David K. Woods, Ph.D.
Just a thought to rework your older code with the older widget, how
about reformatting your large selected content by breaking the
selection down into smaller selections. Perhaps use an iterator, or
generator.

<snip>

Other ideas: for segmenting large selections:
LongRunningTasks - wxPyWiki

Other things to consider.
The segmentation of the content-selection reminded me of the old DC
device context trick used in printing images on old printers using
something called "banding". Which brought to mind that when you
reformat text, sometimes you need to let the widget have enough time
to recalculate it's printing/display properties, as this is an event
driven package and there are not guarentees of the order of
processing. I have no idea if RichTextCtrl is reformatting your
content but not recalculating each content objects properties (ie
margins, etc) sooner then your reformatting method, although I
seriously doubt that's the issue.

Thanks for the suggestions. I've tried something along those lines
already and it hasn't worked. The only thing I've found so far that
prevents the crash after a certain number of characters is to quit and
restart the program. I may be able to take the RichTextBuffer,
manipulate it directly, then put the buffer back into the RichTextCtrl,
but I don't know if I'll be able to make that work. I may also try
manipulating the XML representation of the document, although I
anticipate having trouble finding the starting and ending place of the
control's selection within the XML for the larger document. I may be
able to do something really hacky, like updating part of the text,
saving it, destroying and recreating the control, reloading the modified
text, updating the formatting for the next section ... etc. But I think
I'd rather not go there.

My plan today is to look at slightly older wxPython releases to see if
there's a recent one that avoids the problem. I think 2.9.1.1 was
suggested earlier in this thread. I'll also keep trying to get
wxWidgets 2.9.2 working for me, to pursue getting the underlying problem
addressed at the wxWidgets level if that's where it's coming from.

I appreciate the input.

David

···

--
David K. Woods, Ph.D.
Researcher, Lead Transana Developer
Wisconsin Center for Education Research
University of Wisconsin, Madison
http://www.transana.org