1# Copyright (c) 2019, Enthought Inc.
2# All rights reserved.
3#
4# This software is provided without warranty under the terms of the BSD
5# license included in LICENSE.txt and may be redistributed only
6# under the conditions described in the aforementioned license.  The license
7# is also available online at http://www.enthought.com/licenses/BSD.txt
8# Thanks for using Enthought open source!
9
10
11import textwrap
12import unittest
13
14from pyface.qt import QtGui
15from traitsui.tests._tools import requires_toolkit, ToolkitName
16from traitsui.qt4.helper import wrap_text_with_elision
17from traitsui.qt4.font_trait import create_traitsfont
18
19
20lorem_ipsum = (
21    "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
22    "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
23    "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
24    "commodo consequat.\n"
25    "    \n"
26    "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum "
27    "dolore eu fugiat nulla pariatur.\n"
28    "Excepteur sint occaecat cupidatat non proident, sunt in culpa qui "
29    "officia deserunt mollit anim id est laborum."
30)
31
32
33def get_expected_lines(text, width):
34    expected_lines = []
35    for paragraph in text.splitlines():
36        if not paragraph.strip():
37            expected_lines.append("")
38            continue
39        expected_lines += textwrap.wrap(paragraph, width)
40    return expected_lines
41
42
43@requires_toolkit([ToolkitName.qt])
44class TestWrapText(unittest.TestCase):
45    def test_wrap_text_basic(self):
46        font = create_traitsfont("Courier")
47        font_metrics = QtGui.QFontMetrics(font)
48
49        average_char_width = font_metrics.averageCharWidth()
50        line_spacing = font_metrics.lineSpacing()
51
52        width = 500 * average_char_width
53        height = 100 * line_spacing
54
55        lines = wrap_text_with_elision(lorem_ipsum, font, width, height)
56
57        self.assertEqual(
58            lines, [line.rstrip() for line in lorem_ipsum.splitlines()]
59        )
60
61    def test_wrap_text_empty(self):
62        font = create_traitsfont("Courier")
63        font_metrics = QtGui.QFontMetrics(font)
64
65        average_char_width = font_metrics.averageCharWidth()
66        line_spacing = font_metrics.lineSpacing()
67
68        width = 500 * average_char_width
69        height = 100 * line_spacing
70
71        lines = wrap_text_with_elision("", font, width, height)
72
73        self.assertEqual(lines, [])
74
75    def test_wrap_text_narrow(self):
76        font = create_traitsfont("Courier")
77        font_metrics = QtGui.QFontMetrics(font)
78
79        average_char_width = font_metrics.averageCharWidth()
80        line_spacing = font_metrics.lineSpacing()
81
82        width = 20 * average_char_width
83        height = 100 * line_spacing
84
85        lines = wrap_text_with_elision(lorem_ipsum, font, width, height)
86
87        # add one char slack as depends on OS, exact font, etc.
88        self.assertTrue(all(len(line) <= 21 for line in lines))
89
90    def test_wrap_text_narrow_short(self):
91        font = create_traitsfont("Courier")
92        font_metrics = QtGui.QFontMetrics(font)
93
94        average_char_width = font_metrics.averageCharWidth()
95        line_spacing = font_metrics.lineSpacing()
96
97        width = 20 * average_char_width
98        height = 20 * line_spacing
99
100        lines = wrap_text_with_elision(lorem_ipsum, font, width, height)
101
102        # add one char slack as depends on OS, exact font, etc.
103        self.assertTrue(all(len(line) <= 21 for line in lines))
104        # different os elide the last line slightly differently,
105        # just check end of last line shows elision.
106        # In most systems elision is marked with ellipsis
107        # but it has been reported as "..." on NetBSD.
108        if lines[19][-1] == ".":
109            self.assertEqual(lines[19][-3:], "...")
110        else:
111            self.assertEqual(lines[19][-1], "\u2026")
112
113    def test_wrap_text_short(self):
114        font = create_traitsfont("Courier")
115        font_metrics = QtGui.QFontMetrics(font)
116
117        average_char_width = font_metrics.averageCharWidth()
118        line_spacing = font_metrics.lineSpacing()
119
120        width = 500 * average_char_width
121        height = 3 * line_spacing
122
123        lines = wrap_text_with_elision(lorem_ipsum, font, width, height)
124
125        expected_lines = get_expected_lines(lorem_ipsum, 500)[:3]
126        self.assertEqual(lines, expected_lines)
127