summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorGeeTransit <geetransit@gmail.com>2019-09-05 01:33:34 (GMT)
committerTerry Jan Reedy <tjreedy@udel.edu>2019-09-05 01:33:33 (GMT)
commit2cd902585815582eb059e3b40e014ebe4e7fdee7 (patch)
tree67a45372bd87b7d0020e6c5fdcbf034dc417ad8f /Lib
parent87bd2071c756188b6cd577889fb1682831142ceb (diff)
downloadcpython-2cd902585815582eb059e3b40e014ebe4e7fdee7.zip
cpython-2cd902585815582eb059e3b40e014ebe4e7fdee7.tar.gz
cpython-2cd902585815582eb059e3b40e014ebe4e7fdee7.tar.bz2
bpo-37902: IDLE: Add scrolling for IDLE browsers. (#15368)
Modify the wheel event handler so it can also be used for module, path, and stack browsers. Patch by George Zhang.
Diffstat (limited to 'Lib')
-rw-r--r--Lib/idlelib/NEWS.txt3
-rw-r--r--Lib/idlelib/editor.py25
-rw-r--r--Lib/idlelib/idle_test/test_multicall.py8
-rw-r--r--Lib/idlelib/idle_test/test_tree.py29
-rw-r--r--Lib/idlelib/tree.py31
5 files changed, 75 insertions, 21 deletions
diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt
index 47c2291..c9e846a 100644
--- a/Lib/idlelib/NEWS.txt
+++ b/Lib/idlelib/NEWS.txt
@@ -3,6 +3,9 @@ Released on 2019-10-20?
======================================
+bpo-37092: Add mousewheel scrolling for IDLE module, path, and stack
+browsers. Patch by George Zhang.
+
bpo-35771: To avoid occasional spurious test_idle failures on slower
machines, increase the ``hover_delay`` in test_tooltip.
diff --git a/Lib/idlelib/editor.py b/Lib/idlelib/editor.py
index 793ed3a..5cbf704 100644
--- a/Lib/idlelib/editor.py
+++ b/Lib/idlelib/editor.py
@@ -26,6 +26,7 @@ from idlelib import pyparse
from idlelib import query
from idlelib import replace
from idlelib import search
+from idlelib.tree import wheel_event
from idlelib import window
# The default tab setting for a Text widget, in average-width characters.
@@ -151,9 +152,10 @@ class EditorWindow(object):
else:
# Elsewhere, use right-click for popup menus.
text.bind("<3>",self.right_menu_event)
- text.bind('<MouseWheel>', self.mousescroll)
- text.bind('<Button-4>', self.mousescroll)
- text.bind('<Button-5>', self.mousescroll)
+
+ text.bind('<MouseWheel>', wheel_event)
+ text.bind('<Button-4>', wheel_event)
+ text.bind('<Button-5>', wheel_event)
text.bind('<Configure>', self.handle_winconfig)
text.bind("<<cut>>", self.cut)
text.bind("<<copy>>", self.copy)
@@ -502,23 +504,6 @@ class EditorWindow(object):
self.text.yview(event, *args)
return 'break'
- def mousescroll(self, event):
- """Handle scrollwheel event.
-
- For wheel up, event.delta = 120*n on Windows, -1*n on darwin,
- where n can be > 1 if one scrolls fast. Flicking the wheel
- generates up to maybe 20 events with n up to 10 or more 1.
- Macs use wheel down (delta = 1*n) to scroll up, so positive
- delta means to scroll up on both systems.
-
- X-11 sends Control-Button-4 event instead.
- """
- up = {EventType.MouseWheel: event.delta > 0,
- EventType.Button: event.num == 4}
- lines = -5 if up[event.type] else 5
- self.text.yview_scroll(lines, 'units')
- return 'break'
-
rmenu = None
def right_menu_event(self, event):
diff --git a/Lib/idlelib/idle_test/test_multicall.py b/Lib/idlelib/idle_test/test_multicall.py
index 68156a7..ba582bb 100644
--- a/Lib/idlelib/idle_test/test_multicall.py
+++ b/Lib/idlelib/idle_test/test_multicall.py
@@ -35,6 +35,14 @@ class MultiCallTest(unittest.TestCase):
mctext = self.mc(self.root)
self.assertIsInstance(mctext._MultiCall__binders, list)
+ def test_yview(self):
+ # Added for tree.wheel_event
+ # (it depends on yview to not be overriden)
+ mc = self.mc
+ self.assertIs(mc.yview, Text.yview)
+ mctext = self.mc(self.root)
+ self.assertIs(mctext.yview.__func__, Text.yview)
+
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/Lib/idlelib/idle_test/test_tree.py b/Lib/idlelib/idle_test/test_tree.py
index 9be9abe..b3e4c10 100644
--- a/Lib/idlelib/idle_test/test_tree.py
+++ b/Lib/idlelib/idle_test/test_tree.py
@@ -4,7 +4,7 @@ from idlelib import tree
import unittest
from test.support import requires
requires('gui')
-from tkinter import Tk
+from tkinter import Tk, EventType, SCROLL
class TreeTest(unittest.TestCase):
@@ -29,5 +29,32 @@ class TreeTest(unittest.TestCase):
node.expand()
+class TestScrollEvent(unittest.TestCase):
+
+ def test_wheel_event(self):
+ # Fake widget class containing `yview` only.
+ class _Widget:
+ def __init__(widget, *expected):
+ widget.expected = expected
+ def yview(widget, *args):
+ self.assertTupleEqual(widget.expected, args)
+ # Fake event class
+ class _Event:
+ pass
+ # (type, delta, num, amount)
+ tests = ((EventType.MouseWheel, 120, -1, -5),
+ (EventType.MouseWheel, -120, -1, 5),
+ (EventType.ButtonPress, -1, 4, -5),
+ (EventType.ButtonPress, -1, 5, 5))
+
+ event = _Event()
+ for ty, delta, num, amount in tests:
+ event.type = ty
+ event.delta = delta
+ event.num = num
+ res = tree.wheel_event(event, _Widget(SCROLL, amount, "units"))
+ self.assertEqual(res, "break")
+
+
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/Lib/idlelib/tree.py b/Lib/idlelib/tree.py
index 21426cb..6229be4 100644
--- a/Lib/idlelib/tree.py
+++ b/Lib/idlelib/tree.py
@@ -56,6 +56,30 @@ def listicons(icondir=ICONDIR):
column = 0
root.images = images
+def wheel_event(event, widget=None):
+ """Handle scrollwheel event.
+
+ For wheel up, event.delta = 120*n on Windows, -1*n on darwin,
+ where n can be > 1 if one scrolls fast. Flicking the wheel
+ generates up to maybe 20 events with n up to 10 or more 1.
+ Macs use wheel down (delta = 1*n) to scroll up, so positive
+ delta means to scroll up on both systems.
+
+ X-11 sends Control-Button-4,5 events instead.
+
+ The widget parameter is needed so browser label bindings can pass
+ the underlying canvas.
+
+ This function depends on widget.yview to not be overridden by
+ a subclass.
+ """
+ up = {EventType.MouseWheel: event.delta > 0,
+ EventType.ButtonPress: event.num == 4}
+ lines = -5 if up[event.type] else 5
+ widget = event.widget if widget is None else widget
+ widget.yview(SCROLL, lines, 'units')
+ return 'break'
+
class TreeNode:
@@ -260,6 +284,9 @@ class TreeNode:
anchor="nw", window=self.label)
self.label.bind("<1>", self.select_or_edit)
self.label.bind("<Double-1>", self.flip)
+ self.label.bind("<MouseWheel>", lambda e: wheel_event(e, self.canvas))
+ self.label.bind("<Button-4>", lambda e: wheel_event(e, self.canvas))
+ self.label.bind("<Button-5>", lambda e: wheel_event(e, self.canvas))
self.text_id = id
def select_or_edit(self, event=None):
@@ -410,6 +437,7 @@ class FileTreeItem(TreeItem):
# A canvas widget with scroll bars and some useful bindings
class ScrolledCanvas:
+
def __init__(self, master, **opts):
if 'yscrollincrement' not in opts:
opts['yscrollincrement'] = 17
@@ -431,6 +459,9 @@ class ScrolledCanvas:
self.canvas.bind("<Key-Next>", self.page_down)
self.canvas.bind("<Key-Up>", self.unit_up)
self.canvas.bind("<Key-Down>", self.unit_down)
+ self.canvas.bind("<MouseWheel>", wheel_event)
+ self.canvas.bind("<Button-4>", wheel_event)
+ self.canvas.bind("<Button-5>", wheel_event)
#if isinstance(master, Toplevel) or isinstance(master, Tk):
self.canvas.bind("<Alt-Key-2>", self.zoom_height)
self.canvas.focus_set()