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.
This commit is contained in:
parent
87bd2071c7
commit
2cd9025858
|
@ -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.
|
||||
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -1871,6 +1871,7 @@ Nickolai Zeldovich
|
|||
Yuxiao Zeng
|
||||
Uwe Zessin
|
||||
Cheng Zhang
|
||||
George Zhang
|
||||
Kai Zhu
|
||||
Tarek Ziadé
|
||||
Jelle Zijlstra
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
Add mousewheel scrolling for IDLE module, path, and stack browsers.
|
||||
Patch by George Zhang.
|
Loading…
Reference in New Issue