[Python-checkins] bpo-37706: IDLE - fix sidebar code bug and drag tests (GH-15103)

Miss Islington (bot) webhook-mailer at python.org
Sun Aug 4 12:44:00 EDT 2019


https://github.com/python/cpython/commit/1d2b4dba6ccbeb90ef797034b775c0f1ed17d1a0
commit: 1d2b4dba6ccbeb90ef797034b775c0f1ed17d1a0
branch: 3.8
author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
committer: GitHub <noreply at github.com>
date: 2019-08-04T09:43:56-07:00
summary:

bpo-37706: IDLE - fix sidebar code bug and drag tests (GH-15103)


Convert mouse y to line number in the sidebar rather than the text.
(cherry picked from commit 86f1a18abfee5939452f468d80de998918e2afd2)

Co-authored-by: Tal Einat <taleinat+github at gmail.com>

files:
M Lib/idlelib/idle_test/htest.py
M Lib/idlelib/idle_test/test_sidebar.py
M Lib/idlelib/sidebar.py

diff --git a/Lib/idlelib/idle_test/htest.py b/Lib/idlelib/idle_test/htest.py
index 6990af519b1f..1373b7642a6e 100644
--- a/Lib/idlelib/idle_test/htest.py
+++ b/Lib/idlelib/idle_test/htest.py
@@ -210,13 +210,20 @@ def _wrapper(parent):  # htest #
     'file': 'sidebar',
     'kwds': {},
     'msg': textwrap.dedent("""\
-        Click on the line numbers and drag down below the edge of the
+        1. Click on the line numbers and drag down below the edge of the
         window, moving the mouse a bit and then leaving it there for a while.
         The text and line numbers should gradually scroll down, with the
         selection updated continuously.
-        Do the same as above, dragging to above the window. The text and line
+
+        2. With the lines still selected, click on a line number above the
+        selected lines. Only the line whose number was clicked should be
+        selected.
+
+        3. Repeat step #1, dragging to above the window. The text and line
         numbers should gradually scroll up, with the selection updated
-        continuously."""),
+        continuously.
+
+        4. Repeat step #2, clicking a line number below the selection."""),
     }
 
 _multi_call_spec = {
diff --git a/Lib/idlelib/idle_test/test_sidebar.py b/Lib/idlelib/idle_test/test_sidebar.py
index 07e8f2e96b90..0f5b4c712232 100644
--- a/Lib/idlelib/idle_test/test_sidebar.py
+++ b/Lib/idlelib/idle_test/test_sidebar.py
@@ -240,7 +240,6 @@ def get_width():
         self.assert_sidebar_n_lines(1)
         self.assertEqual(get_width(), 1)
 
-    @unittest.skipIf(platform == 'darwin', 'test tk version dependent')
     def test_click_selection(self):
         self.linenumber.show_sidebar()
         self.text.insert('1.0', 'one\ntwo\nthree\nfour\n')
@@ -254,44 +253,47 @@ def test_click_selection(self):
 
         self.assertEqual(self.get_selection(), ('2.0', '3.0'))
 
-    @unittest.skipIf(platform == 'darwin', 'test tk version dependent')
-    def test_drag_selection_down(self):
-        self.linenumber.show_sidebar()
-        self.text.insert('1.0', 'one\ntwo\nthree\nfour\nfive\n')
-        self.root.update()
+    def simulate_drag(self, start_line, end_line):
+        start_x, start_y = self.get_line_screen_position(start_line)
+        end_x, end_y = self.get_line_screen_position(end_line)
 
-        # Drag from the second line to the fourth line.
-        start_x, start_y = self.get_line_screen_position(2)
-        end_x, end_y = self.get_line_screen_position(4)
         self.linenumber.sidebar_text.event_generate('<Button-1>',
                                                     x=start_x, y=start_y)
-        self.linenumber.sidebar_text.event_generate('<B1-Motion>',
-                                                    x=start_x, y=start_y)
-        self.linenumber.sidebar_text.event_generate('<B1-Motion>',
-                                                    x=end_x, y=end_y)
+        self.root.update()
+
+        def lerp(a, b, steps):
+            """linearly interpolate from a to b (inclusive) in equal steps"""
+            last_step = steps - 1
+            for i in range(steps):
+                yield ((last_step - i) / last_step) * a + (i / last_step) * b
+
+        for x, y in zip(
+                map(int, lerp(start_x, end_x, steps=11)),
+                map(int, lerp(start_y, end_y, steps=11)),
+        ):
+            self.linenumber.sidebar_text.event_generate('<B1-Motion>', x=x, y=y)
+            self.root.update()
+
         self.linenumber.sidebar_text.event_generate('<ButtonRelease-1>',
                                                     x=end_x, y=end_y)
         self.root.update()
+
+    def test_drag_selection_down(self):
+        self.linenumber.show_sidebar()
+        self.text.insert('1.0', 'one\ntwo\nthree\nfour\nfive\n')
+        self.root.update()
+
+        # Drag from the second line to the fourth line.
+        self.simulate_drag(2, 4)
         self.assertEqual(self.get_selection(), ('2.0', '5.0'))
 
-    @unittest.skipIf(platform == 'darwin', 'test tk version dependent')
     def test_drag_selection_up(self):
         self.linenumber.show_sidebar()
         self.text.insert('1.0', 'one\ntwo\nthree\nfour\nfive\n')
         self.root.update()
 
         # Drag from the fourth line to the second line.
-        start_x, start_y = self.get_line_screen_position(4)
-        end_x, end_y = self.get_line_screen_position(2)
-        self.linenumber.sidebar_text.event_generate('<Button-1>',
-                                                    x=start_x, y=start_y)
-        self.linenumber.sidebar_text.event_generate('<B1-Motion>',
-                                                    x=start_x, y=start_y)
-        self.linenumber.sidebar_text.event_generate('<B1-Motion>',
-                                                    x=end_x, y=end_y)
-        self.linenumber.sidebar_text.event_generate('<ButtonRelease-1>',
-                                                    x=end_x, y=end_y)
-        self.root.update()
+        self.simulate_drag(4, 2)
         self.assertEqual(self.get_selection(), ('2.0', '5.0'))
 
     def test_scroll(self):
diff --git a/Lib/idlelib/sidebar.py b/Lib/idlelib/sidebar.py
index 76964a4cdfbe..41c09684a202 100644
--- a/Lib/idlelib/sidebar.py
+++ b/Lib/idlelib/sidebar.py
@@ -204,10 +204,19 @@ def bind_mouse_event(event_name, target_event_name):
                 bind_mouse_event(event_name,
                                  target_event_name=f'<Button-{button}>')
 
+        # This is set by b1_mousedown_handler() and read by
+        # drag_update_selection_and_insert_mark(), to know where dragging
+        # began.
         start_line = None
+        # These are set by b1_motion_handler() and read by selection_handler().
+        # last_y is passed this way since the mouse Y-coordinate is not
+        # available on selection event objects.  last_yview is passed this way
+        # to recognize scrolling while the mouse isn't moving.
+        last_y = last_yview = None
+
         def b1_mousedown_handler(event):
             # select the entire line
-            lineno = self.editwin.getlineno(f"@0,{event.y}")
+            lineno = int(float(self.sidebar_text.index(f"@0,{event.y}")))
             self.text.tag_remove("sel", "1.0", "end")
             self.text.tag_add("sel", f"{lineno}.0", f"{lineno+1}.0")
             self.text.mark_set("insert", f"{lineno+1}.0")
@@ -217,15 +226,20 @@ def b1_mousedown_handler(event):
             start_line = lineno
         self.sidebar_text.bind('<Button-1>', b1_mousedown_handler)
 
-        # These are set by b1_motion_handler() and read by selection_handler();
-        # see below.  last_y is passed this way since the mouse Y-coordinate
-        # is not available on selection event objects.  last_yview is passed
-        # this way to recognize scrolling while the mouse isn't moving.
-        last_y = last_yview = None
+        def b1_mouseup_handler(event):
+            # On mouse up, we're no longer dragging.  Set the shared persistent
+            # variables to None to represent this.
+            nonlocal start_line
+            nonlocal last_y
+            nonlocal last_yview
+            start_line = None
+            last_y = None
+            last_yview = None
+        self.sidebar_text.bind('<ButtonRelease-1>', b1_mouseup_handler)
 
         def drag_update_selection_and_insert_mark(y_coord):
             """Helper function for drag and selection event handlers."""
-            lineno = self.editwin.getlineno(f"@0,{y_coord}")
+            lineno = int(float(self.sidebar_text.index(f"@0,{y_coord}")))
             a, b = sorted([start_line, lineno])
             self.text.tag_remove("sel", "1.0", "end")
             self.text.tag_add("sel", f"{a}.0", f"{b+1}.0")
@@ -253,6 +267,9 @@ def b1_drag_handler(event, *args):
         # while the mouse isn't moving, leading to the above fix not scrolling
         # properly.
         def selection_handler(event):
+            if last_yview is None:
+                # This logic is only needed while dragging.
+                return
             yview = self.sidebar_text.yview()
             if yview != last_yview:
                 self.text.yview_moveto(yview[0])



More information about the Python-checkins mailing list