Browse Source

Control Key Support on Tab and Function keys, Tab Focus Basic implementatin

pull/9/head
Eugenio Parodi 5 years ago
parent
commit
b7aaef8acf
  1. 2
      README.md
  2. 8
      TermTk/TTkCore/constant.py
  3. 54
      TermTk/TTkCore/helper.py
  4. 9
      TermTk/TTkCore/ttk.py
  5. 2
      TermTk/TTkWidgets/lineedit.py
  6. 3
      TermTk/TTkWidgets/widget.py
  7. 119
      TermTk/libbpytop/inputkey.py
  8. 11
      docs/TODO.md

2
README.md

@ -29,7 +29,7 @@ and inspired by a mix of [Qt5](https://www.riverbankcomputing.com/static/Docs/Py
- Only the key combinations forwarded by the terminal emulator used are detected (ALT,CTRL may not be handled)
## Try
Works better on [repl.it](https://repl.it/@EugenioP/pyTermTk)
Works better on [repl.it](https://replit.com/@EugenioP/pyTermTk?v=1)
But you can try it here:
(the console has some terminal size issues, better to run on the **shell** `python3 demo/demo.py -f`)

8
TermTk/TTkCore/constant.py

@ -138,6 +138,14 @@ class TTkConstant:
Character = 0x0001
SpecialKey = 0x0002
NoModifier = 0x00000000 # No modifier key is pressed.
ShiftModifier = 0x02000000 # A Shift key on the keyboard is pressed.
ControlModifier = 0x04000000 # A Ctrl key on the keyboard is pressed.
AltModifier = 0x08000000 # An Alt key on the keyboard is pressed.
MetaModifier = 0x10000000 # A Meta key on the keyboard is pressed.
KeypadModifier = 0x20000000 # A keypad button is pressed.
GroupSwitchModifier = 0x40000000 # X11 only (unless activated on Windows by a command line argument). A Mode_switch key on the keyboard is pressed.
Key_Escape = 0x01000000
Key_Tab = 0x01000001
Key_Backtab = 0x01000002

54
TermTk/TTkCore/helper.py

@ -211,6 +211,60 @@ class TTkHelper:
return (0, 0)
return TTkHelper.absPos(widget.parentWidget())
def _iterWidgets(item):
for child in item.children():
if child.layoutItemType == TTkK.WidgetItem:
if not child.widget().isVisible(): continue
yield child.widget()
for i in TTkHelper._iterWidgets(child.widget().rootLayout()):
yield i
if child.layoutItemType == TTkK.LayoutItem:
for i in TTkHelper._iterWidgets(child):
yield i
def nextFocus(widget, prevFocus=False):
rootWidget = TTkHelper.getOverlay()
if not rootWidget:
rootWidget = TTkHelper._rootCanvas.getWidget()
if widget == rootWidget:
widget = None
first = None
for w in TTkHelper._iterWidgets(rootWidget.rootLayout()):
if not first and w.focusPolicy() & TTkK.TabFocus == TTkK.TabFocus:
first = w
TTkLog.debug(f"{w._name} {widget}")
if widget:
if w == widget:
widget=None
continue
if w.focusPolicy() & TTkK.TabFocus == TTkK.TabFocus:
w.setFocus()
w.update()
return
if first:
first.setFocus()
first.update()
def prevFocus(widget):
rootWidget = TTkHelper.getOverlay()
if not rootWidget:
rootWidget = TTkHelper._rootCanvas.getWidget()
if widget == rootWidget:
widget = None
prev = None
for w in TTkHelper._iterWidgets(rootWidget.rootLayout()):
TTkLog.debug(f"{w._name} {widget}")
if w == widget:
widget=None
if prev:
break
if w.focusPolicy() & TTkK.TabFocus == TTkK.TabFocus:
prev = w
if prev:
prev.setFocus()
prev.update()
@staticmethod
def setFocus(widget):
TTkHelper._focusWidget = widget

9
TermTk/TTkCore/ttk.py

@ -47,6 +47,7 @@ class TTk(TTkWidget):
def __init__(self, *args, **kwargs):
TTkWidget.__init__(self, *args, **kwargs)
self._name = kwargs.get('name' , 'TTk' )
self.events = queue.Queue()
self.key_events = queue.Queue()
self.mouse_events = queue.Queue()
@ -130,9 +131,17 @@ class TTk(TTkWidget):
self.mouseEvent(mevt)
elif evt is TTkK.KEY_EVENT:
kevt = self.key_events.get()
TTkLog.debug(f"Key: {kevt}")
focusWidget = TTkHelper.getFocus()
overlayWidget = TTkHelper.getOverlay()
TTkLog.debug(f"{focusWidget}")
if kevt.key == TTkK.Key_Tab:
# TODO: Handle here if the widget accept the Tab input
if kevt.mod == TTkK.NoModifier:
TTkHelper.nextFocus(focusWidget if focusWidget else self)
if kevt.mod == TTkK.ShiftModifier:
TTkHelper.prevFocus(focusWidget if focusWidget else self)
continue
if focusWidget is not None:
TTkHelper.execShortcut(kevt.key,focusWidget)
focusWidget.keyEvent(kevt)

2
TermTk/TTkWidgets/lineedit.py

@ -56,7 +56,7 @@ class TTkLineEdit(TTkWidget):
self._cursorPos = 0
self._replace=False
self.setMaximumHeight(1)
self.setMinimumSize(10,1)
self.setMinimumSize(1,1)
self.setFocusPolicy(TTkK.ClickFocus + TTkK.TabFocus)
@pyTTkSlot(str)

3
TermTk/TTkWidgets/widget.py

@ -289,7 +289,7 @@ class TTkWidget(TMouseEvents,TKeyEvents):
mouseEvent = True
wx,wy,ww,wh = widget.geometry()
# Skip the mouse event if outside this widget
if x >= wx and x<wx+ww and y>=wy and y<wy+wh:
if wx <= x < wx+ww and wy <= y < wy+wh:
wevt = evt.clone(pos=(x-wx, y-wy))
if mouseEvent:
if wevt is not None:
@ -544,6 +544,7 @@ class TTkWidget(TMouseEvents,TKeyEvents):
def setFocus(self):
tmp = TTkHelper.getFocus()
if tmp == self: return
if tmp is not None:
tmp.clearFocus()
tmp.focusOutEvent()

119
TermTk/libbpytop/inputkey.py

@ -25,57 +25,96 @@
from TermTk.TTkCore.constant import TTkK
class KeyEvent:
__slots__ = ('type', 'key', 'code')
def __init__(self, type:int, key: str, code: str):
__slots__ = ('type', 'key', 'code', 'mod')
def __init__(self, type:int, key: str, code: str, mod: int):
self.type = type
self.key = key
self.mod = mod
self.code = code
def __str__(self):
code = self.code.replace('\033','<ESC>')
return f"KeyEvent: {self.key} {key2str(self.key)} {code}"
return f"KeyEvent: {self.key} {key2str(self.key)} {mod2str(self.mod)} {code}"
@staticmethod
def parse(input_key): # from: Space except "DEL"
if len(input_key) == 1 and "\040" <= input_key != "\177":
return KeyEvent(TTkK.Character, input_key, input_key)
return KeyEvent(TTkK.Character, input_key, input_key, TTkK.NoModifier)
else:
key = _translate_key(input_key)
key, mod = _translate_key(input_key)
if key is not None:
return KeyEvent(TTkK.SpecialKey, key, input_key)
return KeyEvent(TTkK.SpecialKey, key, input_key, mod)
return None
def _translate_key(key):
if key == "\177" : return TTkK.Key_Backspace
elif key == "\t" : return TTkK.Key_Tab
elif key == "\n" : return TTkK.Key_Enter
elif key == "\033[A" : return TTkK.Key_Up
elif key == "\033[B" : return TTkK.Key_Down
elif key == "\033[C" : return TTkK.Key_Right
elif key == "\033[D" : return TTkK.Key_Left
elif key == "\033[5~": return TTkK.Key_PageUp
elif key == "\033[6~": return TTkK.Key_PageDown
if key == "\177" : return TTkK.Key_Backspace , TTkK.NoModifier
elif key == "\t" : return TTkK.Key_Tab , TTkK.NoModifier
elif key == "\033[Z" : return TTkK.Key_Tab , TTkK.ShiftModifier
elif key == "\n" : return TTkK.Key_Enter , TTkK.NoModifier
elif key == "\033[A" : return TTkK.Key_Up , TTkK.NoModifier
elif key == "\033[B" : return TTkK.Key_Down , TTkK.NoModifier
elif key == "\033[C" : return TTkK.Key_Right , TTkK.NoModifier
elif key == "\033[D" : return TTkK.Key_Left , TTkK.NoModifier
elif key == "\033[5~" : return TTkK.Key_PageUp , TTkK.NoModifier
elif key == "\033[6~" : return TTkK.Key_PageDown , TTkK.NoModifier
# Xterm
elif key == "\033[F" : return TTkK.Key_End
elif key == "\033[H" : return TTkK.Key_Home
elif key == "\033[F" : return TTkK.Key_End , TTkK.NoModifier
elif key == "\033[H" : return TTkK.Key_Home , TTkK.NoModifier
# Terminator + tmux
elif key == "\033[4~": return TTkK.Key_End
elif key == "\033[1~": return TTkK.Key_Home
elif key == "\033[2~": return TTkK.Key_Insert
elif key == "\033[3~": return TTkK.Key_Delete
elif key == "\033": return TTkK.Key_Escape
elif key == "\033OP": return TTkK.Key_F1
elif key == "\033OQ": return TTkK.Key_F2
elif key == "\033OR": return TTkK.Key_F3
elif key == "\033OS": return TTkK.Key_F4
elif key == "\033[15~": return TTkK.Key_F5
elif key == "\033[17~": return TTkK.Key_F6
elif key == "\033[18~": return TTkK.Key_F7
elif key == "\033[19~": return TTkK.Key_F8
elif key == "\033[20~": return TTkK.Key_F9
elif key == "\033[21~": return TTkK.Key_F10
elif key == "\033[23~": return TTkK.Key_F11
elif key == "\033[24~": return TTkK.Key_F12
return None
elif key == "\033[4~" : return TTkK.Key_End , TTkK.NoModifier
elif key == "\033[1~" : return TTkK.Key_Home , TTkK.NoModifier
elif key == "\033[2~" : return TTkK.Key_Insert , TTkK.NoModifier
elif key == "\033[3~" : return TTkK.Key_Delete , TTkK.NoModifier
elif key == "\033" : return TTkK.Key_Escape , TTkK.NoModifier
# Function Key
elif key == "\033OP" : return TTkK.Key_F1 , TTkK.NoModifier
elif key == "\033OQ" : return TTkK.Key_F2 , TTkK.NoModifier
elif key == "\033OR" : return TTkK.Key_F3 , TTkK.NoModifier
elif key == "\033OS" : return TTkK.Key_F4 , TTkK.NoModifier
elif key == "\033[15~" : return TTkK.Key_F5 , TTkK.NoModifier
elif key == "\033[17~" : return TTkK.Key_F6 , TTkK.NoModifier
elif key == "\033[18~" : return TTkK.Key_F7 , TTkK.NoModifier
elif key == "\033[19~" : return TTkK.Key_F8 , TTkK.NoModifier
elif key == "\033[20~" : return TTkK.Key_F9 , TTkK.NoModifier
elif key == "\033[21~" : return TTkK.Key_F10 , TTkK.NoModifier
elif key == "\033[23~" : return TTkK.Key_F11 , TTkK.NoModifier
elif key == "\033[24~" : return TTkK.Key_F12 , TTkK.NoModifier
elif key == "\033[1;2P" : return TTkK.Key_F1 , TTkK.ShiftModifier
elif key == "\033[1;2Q" : return TTkK.Key_F2 , TTkK.ShiftModifier
elif key == "\033[1;2R" : return TTkK.Key_F3 , TTkK.ShiftModifier
elif key == "\033[1;2S" : return TTkK.Key_F4 , TTkK.ShiftModifier
elif key == "\033[15;2~": return TTkK.Key_F5 , TTkK.ShiftModifier
elif key == "\033[17;2~": return TTkK.Key_F6 , TTkK.ShiftModifier
elif key == "\033[18;2~": return TTkK.Key_F7 , TTkK.ShiftModifier
elif key == "\033[19;2~": return TTkK.Key_F8 , TTkK.ShiftModifier
elif key == "\033[20;2~": return TTkK.Key_F9 , TTkK.ShiftModifier
elif key == "\033[21;2~": return TTkK.Key_F10 , TTkK.ShiftModifier
elif key == "\033[23;2~": return TTkK.Key_F11 , TTkK.ShiftModifier
elif key == "\033[24;2~": return TTkK.Key_F12 , TTkK.ShiftModifier
elif key == "\033[1;5P" : return TTkK.Key_F1 , TTkK.ControlModifier
elif key == "\033[1;5Q" : return TTkK.Key_F2 , TTkK.ControlModifier
elif key == "\033[1;5R" : return TTkK.Key_F3 , TTkK.ControlModifier
elif key == "\033[1;5S" : return TTkK.Key_F4 , TTkK.ControlModifier
elif key == "\033[15;5~": return TTkK.Key_F5 , TTkK.ControlModifier
elif key == "\033[17;5~": return TTkK.Key_F6 , TTkK.ControlModifier
elif key == "\033[18;5~": return TTkK.Key_F7 , TTkK.ControlModifier
elif key == "\033[19;5~": return TTkK.Key_F8 , TTkK.ControlModifier
elif key == "\033[20;5~": return TTkK.Key_F9 , TTkK.ControlModifier
elif key == "\033[21;5~": return TTkK.Key_F10 , TTkK.ControlModifier
elif key == "\033[23;5~": return TTkK.Key_F11 , TTkK.ControlModifier
elif key == "\033[24;5~": return TTkK.Key_F12 , TTkK.ControlModifier
# elif key == "\033[1;3P" : return TTkK.Key_F1 , TTkK.AltModifier
# elif key == "\033[1;3Q" : return TTkK.Key_F2 , TTkK.AltModifier
elif key == "\033[1;3R" : return TTkK.Key_F3 , TTkK.AltModifier
#elif key == "\033[1;3S" : return TTkK.Key_F4 , TTkK.AltModifier
#elif key == "\033[15;3~": return TTkK.Key_F5 , TTkK.AltModifier
elif key == "\033[17;3~": return TTkK.Key_F6 , TTkK.AltModifier
#elif key == "\033[18;3~": return TTkK.Key_F7 , TTkK.AltModifier
#elif key == "\033[19;3~": return TTkK.Key_F8 , TTkK.AltModifier
elif key == "\033[20;3~": return TTkK.Key_F9 , TTkK.AltModifier
#elif key == "\033[21;3~": return TTkK.Key_F10 , TTkK.AltModifier
elif key == "\033[23;3~": return TTkK.Key_F11 , TTkK.AltModifier
elif key == "\033[24;3~": return TTkK.Key_F12 , TTkK.AltModifier
return None, None
# # elif key == "\033": return TTkK.Key_Tab
# if True: return None
@ -130,6 +169,16 @@ def _translate_key(key):
# elif key == "\033": return TTkK.Key_Any
# return TTkK.NONE
def mod2str(k):
if k == TTkK.NoModifier : return "NoModifier"
if k == TTkK.ShiftModifier : return "ShiftModifier"
if k == TTkK.ControlModifier : return "ControlModifier"
if k == TTkK.AltModifier : return "AltModifier"
if k == TTkK.MetaModifier : return "MetaModifier"
if k == TTkK.KeypadModifier : return "KeypadModifier"
if k == TTkK.GroupSwitchModifier : return "GroupSwitchModifier"
return "NONE!!!"
def key2str(k):
if k == TTkK.Key_Escape : return "Key_Escape"
if k == TTkK.Key_Tab : return "Key_Tab"

11
docs/TODO.md

@ -10,7 +10,6 @@
https://en.wikipedia.org/wiki/Halfwidth_and_Fullwidth_Forms_(Unicode_block)
- [ ] Support Hyperlink: (gnome-terminal)
https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda
- [x] Process child events before parent
## Terminal Helper
@ -25,6 +24,10 @@
- [x] Handle Special Keys (UP, Down, . . .)
- [ ] Handle CTRL-Mouse
- [ ] Handle CTRL,ALT,SHIFT + Key (Tab, UP, Down, . . .)
- [x] Handle SHIFT + Tab
- [x] Handle Tab Focus
- [x] Handle CTRL,ALT,SHIFT + (F1 -> F12)
- [ ] Handle CTRL,ALT,SHIFT + (Up, Down, Left Right)
- [ ] Events
https://tkinterexamples.com/events/events.html
https://www.pythontutorial.net/tkinter/tkinter-event-binding/
@ -110,7 +113,7 @@
- [x] Themes
#### Splitter widget
- [x] Basic Implementation
- [ ] Snap on min/max sizes
- [x] Snap on min/max sizes
- [ ] Events (Signal/Slots)
- [x] Themes
- [ ] Support addItem
@ -123,7 +126,7 @@
- [ ] Keyboard events
#### Spin Box
- [x] Basic Implementation
- [ ] Events (Signal/Slots)
- [x] Events (Signal/Slots)
- [ ] Themes
#### Progress Bar
- [ ] Basic Implementation
@ -139,7 +142,7 @@
- [x] Themes
### Pickers
#### Color Picker
#### Color Picker~/github/Varie/pyTermTk~/github/Varie/pyTermTk
- [x] Basic Implementation
- [x] Events (Signal/Slots)
- [ ] Themes

Loading…
Cancel
Save