def DrawWrappedText(dc, text, rect, measurements=None): """ Simple wordwrap - draws the text into the current DC returns the height of the text that was written measurements is a FontMeasurements object as returned by Styles.getMeasurements() """ if measurements is None: measurements = Styles.getMeasurements(dc.GetFont()) lineHeight = measurements.height spaceWidth = measurements.spaceWidth (rectX, rectY, rectWidth, rectHeight) = rect y = rectY rectRight = rectX + rectWidth rectBottom = rectY + rectHeight # we hit this if you narrow the main window enough: # assert rectHeight >= lineHeight, "Don't have enough room to write anything (have %d, need %d)" % (rectHeight, lineHeight) if rectHeight < lineHeight: return 0 # Can't draw anything for line in text.splitlines(): x = rectX # accumulate text to be written on a line thisLine = u'' for word in line.split(): width = dc.GetTextExtent(word)[0] # if we wrapped but we still can't fit the word, # just truncate it if (width > rectWidth and x == rectX): assert thisLine == u'', "Should be drawing first long word" DrawClippedText(dc, word, rectX, y, rectWidth, width) y += lineHeight continue # see if we want to jump to the next line if (x + width > rectRight): # wrapping, so draw the previous accumulated line if any if thisLine: dc.DrawText(thisLine, rectX, y) thisLine = u'' y += lineHeight x = rectX # if we're out of vertical space, just return if (y + lineHeight > rectBottom): assert thisLine == u'', "shouldn't have any more to draw" return #return y - rectY # total height availableWidth = rectRight - x if width > availableWidth: assert x == rectX and thisLine == u'', "should be writing a long word at the beginning of a line" DrawClippedText(dc, word, rectX, y, availableWidth, width) x += width # x is now past rectRight, so this will force a wrap else: # rather than draw it, just accumulate it thisLine += word + u' ' x += width + spaceWidth # draw the last words on this line, if any if thisLine: dc.DrawText(thisLine, rectX, y) y += lineHeight