-
-
Notifications
You must be signed in to change notification settings - Fork 30.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
gh-42010: IDLE Editor Bottom Scroll Bar #1984
Conversation
Lib/idlelib/editor.py
Outdated
@@ -188,6 +189,9 @@ def __init__(self, flist=None, filename=None, key=None, root=None): | |||
vbar['command'] = text.yview | |||
vbar.pack(side=RIGHT, fill=Y) | |||
text['yscrollcommand'] = vbar.set | |||
hbar['command'] = text.xview | |||
hbar.pack(side='bottom', fill='x') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the fill='x'
should change to fill=X
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mlouielu 'X' or X ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
X
, in tkinter.X
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this request is going to be merged, or it will require many more changes before it is merged, so I'm going to hold off on additional commits for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Either 'x' or X where X == 'x'. For consistency, the latter, with X added to the import.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The more important change is that vbar is now gridded (hence conflict) and hbar must be also. textview.ScrollableTextFrame (wrap=None) uses sticky=EW
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This patch was submitted when I was just getting started on github and before I was ready to make such a change. I am now. Summary of changes now:
- Resolve the merge conflict. We now grid the vbar, and set the command to handle_yview, which scrolls by lines.
- Use textview.AutoHideScrollbar (which requires gridding).
- Disable hbar in PyShell, at least by default.
- Test? We do not need to test the operation of AutoHideScrollbar. That should be in test.test_textview. But test that is present. Check font page font sample test.
Once working, we need to consider global and window configuration options.
Lib/idlelib/editor.py
Outdated
@@ -188,6 +189,9 @@ def __init__(self, flist=None, filename=None, key=None, root=None): | |||
vbar['command'] = text.yview | |||
vbar.pack(side=RIGHT, fill=Y) | |||
text['yscrollcommand'] = vbar.set | |||
hbar['command'] = text.xview | |||
hbar.pack(side='bottom', fill='x') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Either 'x' or X where X == 'x'. For consistency, the latter, with X added to the import.
Lib/idlelib/editor.py
Outdated
@@ -108,6 +108,7 @@ def __init__(self, flist=None, filename=None, key=None, root=None): | |||
'recent-files.lst') | |||
self.text_frame = text_frame = Frame(top) | |||
self.vbar = vbar = Scrollbar(text_frame, name='vbar') | |||
self.hbar = hbar = Scrollbar(text_frame, orient="horizontal", name='hbar') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use textview.AutoHideScrollbar. Unless there is a clear reason otherwise, set the command for this and vbar in the initial call. For the latter, use revised command=self.handle_yview
. I don't believe we need to add a handle_xview
.
Lib/idlelib/editor.py
Outdated
@@ -188,6 +189,9 @@ def __init__(self, flist=None, filename=None, key=None, root=None): | |||
vbar['command'] = text.yview | |||
vbar.pack(side=RIGHT, fill=Y) | |||
text['yscrollcommand'] = vbar.set | |||
hbar['command'] = text.xview |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As said above, set command when init and delete setting here.
Lib/idlelib/editor.py
Outdated
@@ -188,6 +189,9 @@ def __init__(self, flist=None, filename=None, key=None, root=None): | |||
vbar['command'] = text.yview | |||
vbar.pack(side=RIGHT, fill=Y) | |||
text['yscrollcommand'] = vbar.set | |||
hbar['command'] = text.xview | |||
hbar.pack(side='bottom', fill='x') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The more important change is that vbar is now gridded (hence conflict) and hbar must be also. textview.ScrollableTextFrame (wrap=None) uses sticky=EW
.
When you're done making the requested changes, leave the comment: |
Cheryl, if you cannot revise soon (this week), please say so and I will do the above. 3.8.2 and 3.9.0a4 were released today, and I would like to merge well before the next releases. |
2053b25
to
90ba632
Compare
I have made the requested changes; please review again. Terry, I made the suggested changes, but I didn't get to look at it a lot. Bringing up |
Thanks for making the requested changes! @terryjreedy: please review the changes made to this pull request. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cheryl, I tested the patch and initially it seemed fine. Then I encountered the continued flashing that I presume you referred to, and discovered how to reproduce it, and figure out why, I think, but not how to stop it.
@taleinat We are trying to add the as-needed horizontal scrollbar used in the font sample to editor and output windows. When scrolling with the text height fixed, (the initial default), there are tolerable single 'flashes' when the bar is shown or hidden, like seen when context lines are added or deleted. When scrolling with the window height fixed, as when zoomed or after resizing, a minor glitch can happen when the bottom line is the only long line but is mostly covered up by the scrollbar, so that there is nothing visible to scroll. I will come back to how to reproduce this.
In either mode, a long line only at the bottom can cause the bbar to appear and disappear in a loop. To reproduce on my machine with this patch applied, using SourceCodePro size12 font, open configdialog.py. In fixed text mode, scroll down until blank line 252 is the bottom visible line. Move down 1 more with vbar bottom arrow. Long line 253 and hbar appear (with a flash). Move back up with top vbar arrow. Hbar flashes until one scrolls again.
Switch to fixed window mode by slightly increasing its height. Make non-blank line 251 the bottom visible line. A slice of blank line 252 is also displayed but with a small enough window height increase, none of line number 252 will be. Move down with vbar arrow, exposing blank line 252 and bit of long line 253, which will be covered by the hbar. Since none of 253 is visible, the hbar is not needed, so it is removed, exposing a slice of 253, making it needed again. and so on. (I presume something like this happens in the fixed text case when going down and up, even though the text window should be exactly n lines. Only the top (and blank) 1 pixel slice of the long line would be need to be exposed and covered.)
Now make 251 the maximum line number exposed and put the cursor there or above. Move the cursor down with the down arrow key, rather than clicking the vbar down arrow. When scrolling down with the cursor, lines are synchronized with the bottom of the text widget and partial lines are exposed at the top rather the bottom of the text widget. When the cursor exposes line 253, it will be covered up by the hbar. But for me, the top of the cursor is visible, meaning that the blank top slice of 253 is visible, hence the hbar is not removed. This is the minor glitch described above.
The question is how to stop the looping in the situations where it now occurs. I have some vague ideas, but need to sleep soon.
When you're done making the requested changes, leave the comment: |
I never heard of a horizontal scrollwheel. Must be a linux thing with different linux-only button numbers to be bound. |
Sorry I hadn't been more clear in my comment. It's actually a button on my mouse and it's not OS specific. I didn't look at the docs to see what it would map to (if anything) for Tck/Tk. It's just my first natural choice for left/right scrolling and I noticed it didn't work. |
They do exist, e.g. the Logitech MX Master mice have a second horizontal scroll-wheel. |
I was thinking of a 'wheel that scrolls horizontally' as being implemented either with a physical 2nd wheel or a shift button that makes the current wheel be interpreted horizontally (while held down).* Neither the left nor right button are suitable for that (they have other effects), but the editor currently ignores the middle (wheel) button. So we could use it for wheel mode shift. Holding the wheel down while rotating it is harder but is not too bad, especially after just a bit of practice. I believe we could also make the wheel scroll vertically or horizontally when the mouse is over the corresponding scrollbar. But we first need to solve the flash loop. I might ask on SO.
|
One of my ideas was to 'de-bounce' hbar being displayed by rejecting following events that come too quickly. About 20 events per second should be about the fastest for auto-repeat keys and wheel click. I need to see how fast the scrollbar is responding to it hiding the long line that made it show. |
I've worked on this on and off, and all I can say is that the Tk text widget is pretty bad with regard to horizontal scrolling: It sets the horizontal scroll position only according to the currently visible lines! If the text was scrolled to the right, scrolling down to where there are only shorter lines will scroll the text back to the left!! 😠 I've not found any way to change this or work around it, having spent too much time trying... I think the best we can do without going overboard with this is to be make sure to keep the horizontal scrollbar displayed whenever the contents of the text widget are wider than it's display area. My suggestion is to have a separate scrollbar class ("AutoShowHorizontalScollbarForText" ?), identical to the existing AutoShowScrollbar but with this for its set() method: def set(self, lo, hi):
super().set(lo, hi)
text = self.text_widget
lines = text.get('1.0', 'end-1c').split('\n')
longest_line = max(lines, key=len)
width = Font(text, text['font']).measure(longest_line)
inner_padding = sum(map(text.tk.getint, [text.cget('border'),
text.cget('padx')]))
show = width > text.winfo_width() - 2 * inner_padding
if show:
self.grid()
else:
self.grid_remove() In my testing, this completely avoids the issues described in previous comments and does not significantly affect the performance of scrolling. I think this is a relatively simple solution that is a clear improvement on the status quo. |
The other possibility I can think of (the aforementioned "going overboard") is to put the text widget in a frame which auto-resizes to fit the text widget, and then have the outer frame scrolled instead of the text widget, writing the adapters to make it all work. This includes special handling not only of scrolling logic, but also more esoteric text methods such as |
I spent hours trying to get this to work with the Text widget - I couldn't find any way to get it working without jumping around when scrolling vertically due to different line lengths and Tk's Text widget's strange behavior regarding them. As it is, IMO this PR should be closed. If someone would like to tackle this, a different approach would be needed than the one used here. |
@terryjreedy, I propose closing this PR. |
Were the hours spent with the replacement 'see' method or the 'overboard' or both? I would be willing to make this an option if the partial line glitch were fixed (by never allowing them) and the looping were fixed (by adding a much longer delay between changes?). |
The hours were spent trying various ways to get Tk to scroll the text widget properly, reading through its docs, searching online etc. I couldn't find any way to avoid it jumping back left when scrolling up/down to an area with shorter lines. The alternatives would be effectively implementing scrolling behavior ourselves, but I can't possibly see that being worth the extra effort, maintenance burden and potential performance hit for large files.
I couldn't find any reasonable way to achieve these, hence my recommendation to close this. |
This PR is stale because it has been open for 30 days with no activity. |
This missed the boat for inclusion in Python 3.9 which accepts security fixes only as of today. |
This PR is stale because it has been open for 30 days with no activity. |
Quoting @taleinat's latest post here:
Suggesting to apply the pending close label on this PR, unless there still is interest to drive this forward. cc. @terryjreedy @csabella |
I am leaving the issue open and added a comment there. |
Adds a horizontal scroll bar to the IDLE Editor windows.
https://bugs.python.org/issue1207613