Files
server-manager/gui/widgets/entry_undo.py
chrome-storm-c442 5d55d41f34 v1.8.13: fix entry_undo Cyrillic bind crash
tkinter rejects Cyrillic chars in bind(). Use keycode-based
<Control-Key> dispatch instead (same approach as terminal_widget).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 05:30:13 -05:00

61 lines
1.7 KiB
Python

"""
Ctrl+Z / Ctrl+Y undo/redo for CTkEntry widgets.
tk.Entry has no built-in undo, so we track history manually.
"""
def enable_undo(ctk_entry):
"""Add Ctrl+Z undo and Ctrl+Y redo to a CTkEntry widget."""
entry = ctk_entry._entry
history = [entry.get()]
redo_stack = []
_recording = [True]
def _snapshot(*_args):
if not _recording[0]:
return
val = entry.get()
if not history or history[-1] != val:
history.append(val)
redo_stack.clear()
# Cap history size
if len(history) > 200:
del history[:100]
def _undo(event):
if len(history) > 1:
redo_stack.append(history.pop())
_recording[0] = False
entry.delete(0, "end")
entry.insert(0, history[-1])
_recording[0] = True
elif history:
redo_stack.append(history.pop())
_recording[0] = False
entry.delete(0, "end")
_recording[0] = True
return "break"
def _redo(event):
if redo_stack:
val = redo_stack.pop()
history.append(val)
_recording[0] = False
entry.delete(0, "end")
entry.insert(0, val)
_recording[0] = True
return "break"
def _on_ctrl_key(event):
"""Route Ctrl+key by physical keycode (layout-independent)."""
if event.keycode == 90: # Z
return _undo(event)
if event.keycode == 89: # Y
return _redo(event)
return None
entry.bind("<KeyRelease>", _snapshot, add="+")
entry.bind("<Control-z>", _undo)
entry.bind("<Control-y>", _redo)
entry.bind("<Control-Key>", _on_ctrl_key)