Skip to content

Commit 311294b

Browse files
committed
Extend move_widget tests, add preserve_geometry kwarg
The 'preserve_geometry' kwarg to 'move_widget' is passed to 'copy_widget' and allows a user to force the function to automatically reconfigure the widget in the new parent using the old geometry manager information (as it does for the children, by setting the level to 1 at the start of the copy_widget recursive function)
1 parent d63ad46 commit 311294b

File tree

2 files changed

+83
-13
lines changed

2 files changed

+83
-13
lines changed

tests/test_utilities.py

Lines changed: 75 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@
1111

1212

1313
class TestUtilities(BaseWidgetTest):
14+
def assertGeometryInfoEquals(self, info1, info2):
15+
info1.pop("in", None)
16+
info2.pop("in", None)
17+
self.assertEquals(info1, info2)
18+
1419
def setUp(self):
1520
BaseWidgetTest.setUp(self)
1621
self._dummy_flag = False
@@ -37,30 +42,36 @@ def test_move_widget(self):
3742

3843
def test_move_widget_pack(self):
3944
label = ttk.Label(self.window)
40-
label.pack()
45+
label.pack(side=tk.LEFT)
46+
info = label.pack_info()
4147
tl = tk.Toplevel(self.window)
42-
label = move_widget(label, tl)
43-
label.pack()
48+
label = move_widget(label, tl, preserve_geometry=True)
4449
self.assertIsChild(label, tl)
4550
self.assertIn(label, tl.pack_slaves())
51+
self.assertNotIn(label, self.window.pack_slaves())
52+
self.assertGeometryInfoEquals(info, label.pack_info())
4653

4754
def test_move_widget_grid(self):
4855
label = ttk.Label(self.window)
49-
label.grid()
56+
label.grid(row=1, column=1)
57+
info = label.grid_info()
5058
tl = tk.Toplevel(self.window)
51-
label = move_widget(label, tl)
52-
label.grid()
59+
label = move_widget(label, tl, preserve_geometry=True)
5360
self.assertIsChild(label, tl)
54-
self.assertIn(label, tl.grid_slaves())
61+
self.assertIn(label, tl.grid_slaves(row=1, column=1))
62+
self.assertNotIn(label, self.window.grid_slaves(row=1, column=1))
63+
self.assertGeometryInfoEquals(info, label.grid_info())
5564

5665
def test_move_widget_place(self):
5766
label = ttk.Label(self.window)
58-
label.place()
67+
label.place(x=0, y=10)
68+
info = label.place_info()
5969
tl = tk.Toplevel(self.window)
60-
label = move_widget(label, tl)
61-
label.place()
70+
label = move_widget(label, tl, preserve_geometry=True)
6271
self.assertIsChild(label, tl)
6372
self.assertIn(label, tl.place_slaves())
73+
self.assertNotIn(label, self.window.place_slaves())
74+
self.assertGeometryInfoEquals(info, label.place_info())
6475

6576
def test_move_widget_with_binding(self):
6677
label = ttk.Label(self.window)
@@ -123,6 +134,60 @@ def test_move_widget_with_binding_on_parent(self):
123134
self.window.event_generate("<Enter>")
124135
self.assertHasBeenInvoked()
125136

137+
def test_move_widget_with_children_pack(self):
138+
frame = ttk.Frame(self.window)
139+
label = ttk.Label(frame)
140+
parent = tk.Toplevel()
141+
label.pack(side=tk.BOTTOM)
142+
info = label.pack_info()
143+
frame.pack(expand=True)
144+
145+
frame = move_widget(frame, parent)
146+
self.assertTrue(len(frame.pack_slaves()) == 1)
147+
label2 = frame.nametowidget(frame.pack_slaves()[0])
148+
self.assertTrue(label is not label2)
149+
150+
self.assertGeometryInfoEquals(info, label2.pack_info())
151+
self.assertRaises(tk.TclError, label.pack_info)
152+
self.assertRaises(tk.TclError, frame.pack_info) # Frame is not packed
153+
self.assertIn(label2, frame.pack_slaves())
154+
155+
def test_move_widget_with_children_grid(self):
156+
frame = ttk.Frame(self.window)
157+
label = ttk.Label(frame)
158+
parent = tk.Toplevel()
159+
label.grid(row=1, column=1)
160+
info = label.grid_info()
161+
frame.grid(row=1, column=1)
162+
163+
frame = move_widget(frame, parent)
164+
self.assertTrue(len(frame.grid_slaves()) == 1)
165+
label2 = frame.nametowidget(frame.grid_slaves()[0])
166+
self.assertTrue(label is not label2)
167+
168+
self.assertGeometryInfoEquals(info, label2.grid_info())
169+
self.assertRaises(tk.TclError, label.grid_info)
170+
self.assertTrue(len(frame.grid_info()) == 0) # Frame is not in grid
171+
self.assertIn(label2, frame.grid_slaves())
172+
173+
def test_move_widget_with_children_place(self):
174+
frame = ttk.Frame(self.window)
175+
label = ttk.Label(frame)
176+
parent = tk.Toplevel()
177+
label.place(x=53, y=13)
178+
info = label.place_info()
179+
frame.place(x=100, y=10)
180+
181+
frame = move_widget(frame, parent)
182+
self.assertTrue(len(frame.place_slaves()) == 1)
183+
label2 = frame.nametowidget(frame.place_slaves()[0])
184+
self.assertTrue(label is not label2)
185+
186+
self.assertGeometryInfoEquals(info, label2.place_info())
187+
self.assertRaises(tk.TclError, label.place_info)
188+
self.assertTrue(len(frame.place_info()) == 0)
189+
self.assertIn(label2, frame.place_slaves())
190+
126191
def test_parse_geometry(self):
127192
g = parse_geometry('1x1+1+1')
128193
self.assertEqual(g, (1, 1, 1, 1))

ttkwidgets/utilities.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ def copy_widget(widget, new_parent, level=0):
5151
widget._tclCommands = None # Preserve bound functions
5252
script = widget.bind(b)
5353
rv.bind(b, script)
54-
5554
if level > 0:
5655
if widget.grid_info(): # if geometry manager is grid
5756
temp = widget.grid_info()
@@ -66,6 +65,7 @@ def copy_widget(widget, new_parent, level=0):
6665
del temp['in']
6766
rv.pack(**temp)
6867
level += 1
68+
6969
if widget.pack_slaves(): # subwidgets are using the pack() geometry manager
7070
for child in widget.pack_slaves():
7171
copy_widget(child, rv, level)
@@ -75,16 +75,21 @@ def copy_widget(widget, new_parent, level=0):
7575
return rv
7676

7777

78-
def move_widget(widget, new_parent):
78+
def move_widget(widget, new_parent, preserve_geometry=False):
7979
"""
8080
Moves widget to new_parent
8181
8282
:param widget: widget to move
83+
:type widget: tk.Widget
8384
:param new_parent: new parent for the widget
85+
:type new_parent: tk.Widget
86+
:param preserve_geometry: Whether to preserve the geometry of the
87+
widget in the old parent into the new parent
88+
:type preserve_geometry: bool
8489
8590
:return: moved widget reference
8691
"""
87-
rv = copy_widget(widget, new_parent)
92+
rv = copy_widget(widget, new_parent, level=preserve_geometry)
8893
widget.destroy()
8994
return rv
9095

0 commit comments

Comments
 (0)