Browse Source

Added up/down to switch focus, Moved key/mouse events in a separate routine

pull/50/head
Eugenio Parodi 4 years ago
parent
commit
8de37bca0b
  1. 7
      Makefile
  2. 24
      TermTk/TTkCore/draw.py
  3. 151
      TermTk/TTkCore/ttk.py
  4. 2
      TermTk/TTkWidgets/button.py

7
Makefile

@ -6,6 +6,13 @@
pip install -r docs/requirements.txt
# Add "Signal" option in the method domains
patch -p3 -d .venv/lib/python3*/ < docs/sphynx.001.signal.patch
# Update/Regen
# # Docs
# pip install sphinx sphinx-epytext sphinx-autodocgen sphinx-rtd-theme
# # Test
# pip install flake8 pytest
# # Build
# pip install build twine
# Regen requirements;
# pip freeze > docs/requirements.txt

24
TermTk/TTkCore/draw.py

@ -1,24 +0,0 @@
#!/usr/bin/env python3
# MIT License
#
# Copyright (c) 2021 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

151
TermTk/TTkCore/ttk.py

@ -45,6 +45,7 @@ class TTk(TTkWidget):
'_events', '_key_events', '_mouse_events', '_screen_events',
'_title',
'_sigmask',
'_lastMultiTap',
#Signals
'eventKeyPress', 'eventMouse' )
@ -114,7 +115,7 @@ class TTk(TTkWidget):
self._running = True
# Keep track of the multiTap to avoid the extra key release
lastMultiTap = False
self._lastMultiTap = False
TTkTerm.init(title=self._title, sigmask=self._sigmask)
self._mainloop()
#except Exception as e:
@ -128,77 +129,9 @@ class TTk(TTkWidget):
# Main Loop
evt = self._events.get()
if evt is TTkK.MOUSE_EVENT:
mevt = self._mouse_events.get()
self.eventMouse.emit(mevt)
# Upload the global mouse position
# Mainly used by the drag pixmap display
TTkHelper.setMousePos((mevt.x,mevt.y))
# Avoid to broadcast a key release after a multitap event
if mevt.evt == TTkK.Release and lastMultiTap: continue
lastMultiTap = mevt.tap > 1
if ( TTkHelper.isDnD() and
mevt.evt != TTkK.Drag and
mevt.evt != TTkK.Release ):
# Clean Drag Drop status for any event that is not
# Mouse Drag, Key Release
TTkHelper.dndEnd()
# Mouse Events forwarded straight to the Focus widget:
# - Drag
# - Move
# - Release
focusWidget = TTkHelper.getFocus()
if ( focusWidget is not None and
mevt.evt != TTkK.Press and
mevt.key != TTkK.Wheel and
not TTkHelper.isDnD() ) :
x,y = TTkHelper.absPos(focusWidget)
nmevt = mevt.clone(pos=(mevt.x-x, mevt.y-y))
focusWidget.mouseEvent(nmevt)
else:
# Sometimes the release event is not retrieved
if ( focusWidget and
focusWidget._pendingMouseRelease and
not TTkHelper.isDnD() ):
focusWidget.mouseEvent(nmevt.clone(evt=TTkK.Release))
focusWidget._pendingMouseRelease = False
# Adding this Crappy logic to handle a corner case in the drop routine
# where the mouse is leaving any widget able to handle the drop event
if not self.mouseEvent(mevt):
if dndw := TTkHelper.dndWidget():
dndw.dragLeaveEvent(TTkHelper.dndGetDrag().getDragLeaveEvent(mevt))
TTkHelper.dndEnter(None)
if mevt.evt == TTkK.Press and focusWidget:
focusWidget.clearFocus()
# Clean the Drag and Drop in case of mouse release
if mevt.evt == TTkK.Release:
TTkHelper.dndEnd()
self._mouse_event()
elif evt is TTkK.KEY_EVENT:
keyHandled = False
kevt = self._key_events.get()
self.eventKeyPress.emit(kevt)
# TTkLog.debug(f"Key: {kevt}")
focusWidget = TTkHelper.getFocus()
# TTkLog.debug(f"{focusWidget}")
if focusWidget is not None:
TTkHelper.execShortcut(kevt.key,focusWidget)
keyHandled = focusWidget.keyEvent(kevt)
else:
TTkHelper.execShortcut(kevt.key)
# Handle Next Focus Key Binding
if not keyHandled and \
((kevt.key == TTkK.Key_Tab and kevt.mod == TTkK.NoModifier) or
( kevt.key == TTkK.Key_Right )):
TTkHelper.nextFocus(focusWidget if focusWidget else self)
# Handle Prev Focus Key Binding
if not keyHandled and \
((kevt.key == TTkK.Key_Tab and kevt.mod == TTkK.ShiftModifier) or
( kevt.key == TTkK.Key_Left )):
TTkHelper.prevFocus(focusWidget if focusWidget else self)
self._key_event()
elif evt is TTkK.TIME_EVENT:
size = os.get_terminal_size()
self.setGeometry(0,0,size.columns,size.lines)
@ -216,6 +149,79 @@ class TTk(TTkWidget):
TTkLog.error(f"Unhandled Event {evt}")
break
def _mouse_event(self):
mevt = self._mouse_events.get()
self.eventMouse.emit(mevt)
# Upload the global mouse position
# Mainly used by the drag pixmap display
TTkHelper.setMousePos((mevt.x,mevt.y))
# Avoid to broadcast a key release after a multitap event
if mevt.evt == TTkK.Release and self._lastMultiTap: return
self._lastMultiTap = mevt.tap > 1
if ( TTkHelper.isDnD() and
mevt.evt != TTkK.Drag and
mevt.evt != TTkK.Release ):
# Clean Drag Drop status for any event that is not
# Mouse Drag, Key Release
TTkHelper.dndEnd()
# Mouse Events forwarded straight to the Focus widget:
# - Drag
# - Move
# - Release
focusWidget = TTkHelper.getFocus()
if ( focusWidget is not None and
mevt.evt != TTkK.Press and
mevt.key != TTkK.Wheel and
not TTkHelper.isDnD() ) :
x,y = TTkHelper.absPos(focusWidget)
nmevt = mevt.clone(pos=(mevt.x-x, mevt.y-y))
focusWidget.mouseEvent(nmevt)
else:
# Sometimes the release event is not retrieved
if ( focusWidget and
focusWidget._pendingMouseRelease and
not TTkHelper.isDnD() ):
focusWidget.mouseEvent(mevt.clone(evt=TTkK.Release))
focusWidget._pendingMouseRelease = False
# Adding this Crappy logic to handle a corner case in the drop routine
# where the mouse is leaving any widget able to handle the drop event
if not self.mouseEvent(mevt):
if dndw := TTkHelper.dndWidget():
dndw.dragLeaveEvent(TTkHelper.dndGetDrag().getDragLeaveEvent(mevt))
TTkHelper.dndEnter(None)
if mevt.evt == TTkK.Press and focusWidget:
focusWidget.clearFocus()
# Clean the Drag and Drop in case of mouse release
if mevt.evt == TTkK.Release:
TTkHelper.dndEnd()
def _key_event(self):
kevt = self._key_events.get()
self.eventKeyPress.emit(kevt)
keyHandled = False
# TTkLog.debug(f"Key: {kevt}")
focusWidget = TTkHelper.getFocus()
# TTkLog.debug(f"{focusWidget}")
if focusWidget is not None:
TTkHelper.execShortcut(kevt.key,focusWidget)
keyHandled = focusWidget.keyEvent(kevt)
else:
TTkHelper.execShortcut(kevt.key)
# Handle Next Focus Key Binding
if not keyHandled and \
((kevt.key == TTkK.Key_Tab and kevt.mod == TTkK.NoModifier) or
( kevt.key == TTkK.Key_Right or kevt.key == TTkK.Key_Down)):
TTkHelper.nextFocus(focusWidget if focusWidget else self)
# Handle Prev Focus Key Binding
if not keyHandled and \
((kevt.key == TTkK.Key_Tab and kevt.mod == TTkK.ShiftModifier) or
( kevt.key == TTkK.Key_Left or kevt.key == TTkK.Key_Up)):
TTkHelper.prevFocus(focusWidget if focusWidget else self)
def _time_event(self):
self._events.put(TTkK.TIME_EVENT)
@ -238,9 +244,6 @@ class TTk(TTkWidget):
self._input.get_key(_inputCallback)
self._input.close()
def _canvas_thread(self):
pass
def quit(self):
'''Tells the application to exit with a return code.'''
self._events.put(TTkK.QUIT_EVENT)

2
TermTk/TTkWidgets/button.py

@ -222,7 +222,7 @@ class TTkButton(TTkWidget):
if self._border:
self._canvas.drawButtonBox(pos=(0,0),size=(self._width,self._height),color=borderColor, grid=grid)
for i in range(1,h-1):
self._canvas.drawText(pos=(1,i) ,text=" "*w)
self._canvas.drawText(pos=(1,i) ,text=TTkString(" "*w, textColor))
self._canvas.drawText(pos=(1,y) ,text=text)
else:
self._canvas.drawText(pos=(1,1) ,text=text)

Loading…
Cancel
Save