summaryrefslogtreecommitdiffstats
path: root/Lib/idlelib
diff options
context:
space:
mode:
authorTal Einat <taleinat+github@gmail.com>2019-08-04 16:25:27 (GMT)
committerTerry Jan Reedy <tjreedy@udel.edu>2019-08-04 16:25:27 (GMT)
commit86f1a18abfee5939452f468d80de998918e2afd2 (patch)
tree399d2737cec98ab687f2136263ef99d7aad4f131 /Lib/idlelib
parent18b711c5a7f90d88fb74748f18fa8ef49d8486c7 (diff)
downloadcpython-86f1a18abfee5939452f468d80de998918e2afd2.zip
cpython-86f1a18abfee5939452f468d80de998918e2afd2.tar.gz
cpython-86f1a18abfee5939452f468d80de998918e2afd2.tar.bz2
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.
Diffstat (limited to 'Lib/idlelib')
-rw-r--r--Lib/idlelib/idle_test/htest.py13
-rw-r--r--Lib/idlelib/idle_test/test_sidebar.py52
-rw-r--r--Lib/idlelib/sidebar.py31
3 files changed, 61 insertions, 35 deletions
diff --git a/Lib/idlelib/idle_test/htest.py b/Lib/idlelib/idle_test/htest.py
index 6990af5..1373b76 100644
--- a/Lib/idlelib/idle_test/htest.py
+++ b/Lib/idlelib/idle_test/htest.py
@@ -210,13 +210,20 @@ _linenumbers_drag_scrolling_spec = {
'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 07e8f2e..0f5b4c7 100644
--- a/Lib/idlelib/idle_test/test_sidebar.py
+++ b/Lib/idlelib/idle_test/test_sidebar.py
@@ -240,7 +240,6 @@ class LineNumbersTest(unittest.TestCase):
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 @@ class LineNumbersTest(unittest.TestCase):
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 76964a4..41c0968 100644
--- a/Lib/idlelib/sidebar.py
+++ b/Lib/idlelib/sidebar.py
@@ -204,10 +204,19 @@ class LineNumbers(BaseSideBar):
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 @@ class LineNumbers(BaseSideBar):
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 @@ class LineNumbers(BaseSideBar):
# 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])