1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
|
# (C) Copyright 2004-2023 Enthought, Inc., Austin, TX
# All rights reserved.
#
# This software is provided without warranty under the terms of the BSD
# license included in LICENSE.txt and may be redistributed only under
# the conditions described in the aforementioned license. The license
# is also available online at http://www.enthought.com/licenses/BSD.txt
#
# Thanks for using Enthought open source!
from pyface.qt import QtCore, QtGui
from pyface.ui_traits import HasBorder
from traits.api import Int
from traitsui.tree_node_renderer import AbstractTreeNodeRenderer
from .helper import wrap_text_with_elision
class WordWrapRenderer(AbstractTreeNodeRenderer):
"""A renderer that wraps the label text across multiple lines."""
#: The padding around the text.
padding = HasBorder(0)
#: The a good size for the width of the item.
width_hint = Int(100)
#: The maximum number of lines to show without eliding.
max_lines = Int(5)
#: The extra border applied by Qt internally
# XXX get this dynamically from Qt? How?
extra_space = Int(8)
def paint(self, editor, node, column, object, paint_context):
"""Paint word-wrapped text with elision."""
painter, option, index = paint_context
text = self.get_label(node, object, column)
if editor.factory.show_icons:
icon_width = option.decorationSize.width() + self.extra_space
icon_height = option.decorationSize.height()
else:
icon_width = 0
icon_height = 0
x = option.rect.left() + icon_width + self.padding.left
y = option.rect.top() + self.padding.top
width = (
option.rect.width()
- icon_width
- self.padding.left
- self.padding.right
)
height = option.rect.height() - self.padding.top - self.padding.bottom
lines = wrap_text_with_elision(text, option.font, width, height)
old_pen = painter.pen()
if bool(option.state & QtGui.QStyle.StateFlag.State_Selected):
painter.setPen(QtGui.QPen(option.palette.highlightedText(), 0))
try:
rect = painter.drawText(
x, y, width, height, option.displayAlignment, "\n".join(lines)
)
finally:
painter.setPen(old_pen)
def size(self, editor, node, column, object, size_context):
"""Return the preferred size for the word-wrapped text
Parameters
----------
node : ITreeNode instance
The tree node to render.
column : int
The column in the tree that should be rendererd.
object : object
The underlying object being edited.
size_context : object
A toolkit-dependent context for performing sizing operations.
Returns
-------
size : tuple of (width, height) or None
"""
option, index = size_context
font_metrics = QtGui.QFontMetrics(option.font)
text = self.get_label(node, object, column)
if editor.factory.show_icons:
icon_size = option.decorationSize
icon_width = icon_size.width()
icon_height = icon_size.height()
else:
icon_width = 0
icon_height = 0
width = (
self.width_hint
- icon_width
- self.padding.left
- self.padding.right
)
max_height = self.max_lines * font_metrics.lineSpacing()
lines = wrap_text_with_elision(text, option.font, width, max_height)
text_height = len(lines) * font_metrics.lineSpacing()
height = (
max(icon_height, text_height)
+ self.padding.top
+ self.padding.bottom
+ self.extra_space
)
return self.width_hint, height
|