• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1import unittest
2import sys
3import tkinter
4from tkinter import ttk
5from test import support
6from test.support import requires, run_unittest
7from tkinter.test.support import AbstractTkTest
8
9requires('gui')
10
11CLASS_NAMES = [
12    '.', 'ComboboxPopdownFrame', 'Heading',
13    'Horizontal.TProgressbar', 'Horizontal.TScale', 'Item', 'Sash',
14    'TButton', 'TCheckbutton', 'TCombobox', 'TEntry',
15    'TLabelframe', 'TLabelframe.Label', 'TMenubutton',
16    'TNotebook', 'TNotebook.Tab', 'Toolbutton', 'TProgressbar',
17    'TRadiobutton', 'Treeview', 'TScale', 'TScrollbar', 'TSpinbox',
18    'Vertical.TProgressbar', 'Vertical.TScale'
19]
20
21class StyleTest(AbstractTkTest, unittest.TestCase):
22
23    def setUp(self):
24        super().setUp()
25        self.style = ttk.Style(self.root)
26
27
28    def test_configure(self):
29        style = self.style
30        style.configure('TButton', background='yellow')
31        self.assertEqual(style.configure('TButton', 'background'),
32            'yellow')
33        self.assertIsInstance(style.configure('TButton'), dict)
34
35
36    def test_map(self):
37        style = self.style
38
39        # Single state
40        for states in ['active'], [('active',)]:
41            with self.subTest(states=states):
42                style.map('TButton', background=[(*states, 'white')])
43                expected = [('active', 'white')]
44                self.assertEqual(style.map('TButton', 'background'), expected)
45                m = style.map('TButton')
46                self.assertIsInstance(m, dict)
47                self.assertEqual(m['background'], expected)
48
49        # Multiple states
50        for states in ['pressed', '!disabled'], ['pressed !disabled'], [('pressed', '!disabled')]:
51            with self.subTest(states=states):
52                style.map('TButton', background=[(*states, 'black')])
53                expected = [('pressed', '!disabled', 'black')]
54                self.assertEqual(style.map('TButton', 'background'), expected)
55                m = style.map('TButton')
56                self.assertIsInstance(m, dict)
57                self.assertEqual(m['background'], expected)
58
59        # Default state
60        for states in [], [''], [()]:
61            with self.subTest(states=states):
62                style.map('TButton', background=[(*states, 'grey')])
63                expected = [('grey',)]
64                self.assertEqual(style.map('TButton', 'background'), expected)
65                m = style.map('TButton')
66                self.assertIsInstance(m, dict)
67                self.assertEqual(m['background'], expected)
68
69
70    def test_lookup(self):
71        style = self.style
72        style.configure('TButton', background='yellow')
73        style.map('TButton', background=[('active', 'background', 'blue')])
74
75        self.assertEqual(style.lookup('TButton', 'background'), 'yellow')
76        self.assertEqual(style.lookup('TButton', 'background',
77            ['active', 'background']), 'blue')
78        self.assertEqual(style.lookup('TButton', 'optionnotdefined',
79            default='iknewit'), 'iknewit')
80
81
82    def test_layout(self):
83        style = self.style
84        self.assertRaises(tkinter.TclError, style.layout, 'NotALayout')
85        tv_style = style.layout('Treeview')
86
87        # "erase" Treeview layout
88        style.layout('Treeview', '')
89        self.assertEqual(style.layout('Treeview'),
90            [('null', {'sticky': 'nswe'})]
91        )
92
93        # restore layout
94        style.layout('Treeview', tv_style)
95        self.assertEqual(style.layout('Treeview'), tv_style)
96
97        # should return a list
98        self.assertIsInstance(style.layout('TButton'), list)
99
100        # correct layout, but "option" doesn't exist as option
101        self.assertRaises(tkinter.TclError, style.layout, 'Treeview',
102            [('name', {'option': 'inexistent'})])
103
104
105    def test_theme_use(self):
106        self.assertRaises(tkinter.TclError, self.style.theme_use,
107            'nonexistingname')
108
109        curr_theme = self.style.theme_use()
110        new_theme = None
111        for theme in self.style.theme_names():
112            if theme != curr_theme:
113                new_theme = theme
114                self.style.theme_use(theme)
115                break
116        else:
117            # just one theme available, can't go on with tests
118            return
119
120        self.assertFalse(curr_theme == new_theme)
121        self.assertFalse(new_theme != self.style.theme_use())
122
123        self.style.theme_use(curr_theme)
124
125
126    def test_configure_custom_copy(self):
127        style = self.style
128
129        curr_theme = self.style.theme_use()
130        self.addCleanup(self.style.theme_use, curr_theme)
131        for theme in self.style.theme_names():
132            self.style.theme_use(theme)
133            for name in CLASS_NAMES:
134                default = style.configure(name)
135                if not default:
136                    continue
137                with self.subTest(theme=theme, name=name):
138                    if support.verbose >= 2:
139                        print('configure', theme, name, default)
140                    if (theme in ('vista', 'xpnative')
141                            and sys.getwindowsversion()[:2] == (6, 1)):
142                        # Fails on the Windows 7 buildbot
143                        continue
144                    newname = f'C.{name}'
145                    self.assertEqual(style.configure(newname), None)
146                    style.configure(newname, **default)
147                    self.assertEqual(style.configure(newname), default)
148                    for key, value in default.items():
149                        self.assertEqual(style.configure(newname, key), value)
150
151
152    def test_map_custom_copy(self):
153        style = self.style
154
155        curr_theme = self.style.theme_use()
156        self.addCleanup(self.style.theme_use, curr_theme)
157        for theme in self.style.theme_names():
158            self.style.theme_use(theme)
159            for name in CLASS_NAMES:
160                default = style.map(name)
161                if not default:
162                    continue
163                with self.subTest(theme=theme, name=name):
164                    if support.verbose >= 2:
165                        print('map', theme, name, default)
166                    if (theme in ('vista', 'xpnative')
167                            and sys.getwindowsversion()[:2] == (6, 1)):
168                        # Fails on the Windows 7 buildbot
169                        continue
170                    newname = f'C.{name}'
171                    self.assertEqual(style.map(newname), {})
172                    style.map(newname, **default)
173                    self.assertEqual(style.map(newname), default)
174                    for key, value in default.items():
175                        self.assertEqual(style.map(newname, key), value)
176
177
178tests_gui = (StyleTest, )
179
180if __name__ == "__main__":
181    run_unittest(*tests_gui)
182