1  import unittest
       2  import sys
       3  import tkinter
       4  from tkinter import ttk
       5  from test import support
       6  from test.support import requires
       7  from test.test_tkinter.support import AbstractTkTest, get_tk_patchlevel
       8  
       9  requires('gui')
      10  
      11  CLASS_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  
      21  class ESC[4;38;5;81mStyleTest(ESC[4;38;5;149mAbstractTkTest, ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
      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                      if theme == 'alt' and name == '.' and get_tk_patchlevel(self.root) < (8, 6, 1):
     174                          default['embossed'] = [('disabled', '1')]
     175                      self.assertEqual(style.map(newname), default)
     176                      for key, value in default.items():
     177                          self.assertEqual(style.map(newname, key), value)
     178  
     179  
     180  if __name__ == "__main__":
     181      unittest.main()