Browse Source

Merge pull request #10 from ceccopierangiolieugenio/List_KEY_Mouse_Rework

List key mouse rework
pull/11/head
Ceccopierangiolieugenio 5 years ago committed by GitHub
parent
commit
64f37f5e16
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      TermTk/TTkCore/canvas.py
  2. 22
      TermTk/TTkCore/helper.py
  3. 4
      TermTk/TTkCore/ttk.py
  4. 2
      TermTk/TTkWidgets/list.py
  5. 59
      TermTk/TTkWidgets/listwidget.py
  6. 61
      TermTk/TTkWidgets/menubar.py
  7. 9
      TermTk/TTkWidgets/widget.py
  8. 6
      TermTk/libbpytop/input.py
  9. 4
      demo/showcase/menubar.py
  10. 4
      docs/TODO.md

2
TermTk/TTkCore/canvas.py

@ -468,7 +468,7 @@ class TTkCanvas:
self.drawText(pos=(x+1,y), color=color ,text=text)
off = 1
else:
self.drawText(pos=(x,y), color=color ,text=text)
self.drawText(pos=(x,y), width=width, color=color ,text=text)
if submenu:
self._set(y,x+width-1, mb[5], color)
off = 0

22
TermTk/TTkCore/helper.py

@ -42,6 +42,7 @@ class TTkHelper:
def __init__(self,x,y,widget):
self._widget = widget
widget.move(x,y)
_savedFocus = None
_overlay = []
class _Shortcut():
@ -111,6 +112,9 @@ class TTkHelper:
def overlay(caller, widget, x, y):
wx, wy = TTkHelper.absPos(caller)
w,h = widget.size()
if not TTkHelper._savedFocus and \
not TTkHelper.isOverlay(TTkHelper._focusWidget):
TTkHelper._savedFocus = TTkHelper._focusWidget
# Try to keep the overlay widget inside the terminal
wx = max(0, wx+x if wx+x+w < TTkGlbl.term_w else TTkGlbl.term_w-w )
wy = max(0, wy+y if wy+y+h < TTkGlbl.term_h else TTkGlbl.term_h-h )
@ -130,6 +134,24 @@ class TTkHelper:
for widget in TTkHelper._overlay:
TTkHelper._rootWidget.rootLayout().removeWidget(widget._widget)
TTkHelper._overlay = []
if TTkHelper._focusWidget:
TTkHelper._focusWidget.clearFocus()
if TTkHelper._savedFocus:
bk = TTkHelper._savedFocus
TTkHelper._savedFocus = None
bk.setFocus()
@staticmethod
def removeSingleOverlay(widget):
if len(TTkHelper._overlay) <= 1:
return TTkHelper.removeOverlay()
rootWidget = TTkHelper.rootOverlay(widget)
rootWidget
for o in TTkHelper._overlay:
if o._widget == rootWidget:
TTkHelper._overlay.remove(o)
TTkHelper._rootWidget.rootLayout().removeWidget(rootWidget)
TTkHelper._overlay[-1]._widget.setFocus()
@staticmethod
def paintAll():

4
TermTk/TTkCore/ttk.py

@ -120,6 +120,10 @@ class TTk(TTkWidget):
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:
focusWidget.mouseEvent(nmevt.clone(evt=TTkK.Release))
focusWidget._pendingMouseRelease = False
self.mouseEvent(mevt)
elif evt is TTkK.KEY_EVENT:
keyHandled = False

2
TermTk/TTkWidgets/list.py

@ -35,7 +35,7 @@ class TTkList(TTkAbstractScrollArea):
TTkAbstractScrollArea.__init__(self, *args, **kwargs)
self._name = kwargs.get('name' , 'TTkList' )
if 'parent' in kwargs: kwargs.pop('parent')
self._listView = TTkListWidget(*args, **kwargs)
self._listView = kwargs.get('listWidget',TTkListWidget(*args, **kwargs))
self.setViewport(self._listView)
self.itemClicked = self._listView.itemClicked
self.textClicked = self._listView.textClicked

59
TermTk/TTkWidgets/listwidget.py

@ -31,15 +31,17 @@ from TermTk.TTkWidgets.widget import TTkWidget
from TermTk.TTkWidgets.label import TTkLabel
from TermTk.TTkAbstract.abstractscrollview import TTkAbstractScrollView
class _TTkListWidgetText(TTkLabel):
__slots__ = ('clicked', '_selected', '_highlighted')
class TTkAbstractListItem(TTkLabel):
__slots__ = ('_pressed', '_selected', '_highlighted', 'listItemClicked')
def __init__(self, *args, **kwargs):
TTkLabel.__init__(self, *args, **kwargs)
self._name = kwargs.get('name' , '_TTkListWidgetText' )
self._name = kwargs.get('name' , 'TTkAbstractListItem' )
# Define Signals
self.clicked = pyTTkSignal(_TTkListWidgetText)
self.listItemClicked = pyTTkSignal(TTkAbstractListItem)
self._selected = False
self._pressed = False
self._highlighted = False
self.setFocusPolicy(TTkK.ClickFocus)
def _updateColor(self):
if self._highlighted:
@ -52,8 +54,19 @@ class _TTkListWidgetText(TTkLabel):
else:
self.color = TTkCfg.theme.listColor
def keyEvent(self, evt):
return self.parentWidget().keyEvent(evt)
def mousePressEvent(self, evt):
self._pressed = True
self.highlighted = True
self.update()
return True
def mouseReleaseEvent(self, evt):
self.clicked.emit(self)
self._pressed = False
self.listItemClicked.emit(self)
self.update()
return True
@property
@ -101,19 +114,25 @@ class TTkListWidget(TTkAbstractScrollView):
x,y = self.getViewOffsets()
self.layout().groupMoveTo(-x,-y)
@pyTTkSlot(_TTkListWidgetText)
@pyTTkSlot(TTkAbstractListItem)
def _labelSelectedHandler(self, label):
if self._selectionMode == TTkK.SingleSelection:
for i in self._selectedItems:
i.selected = False
i.color = TTkCfg.theme.listColor
for item in self._selectedItems:
item.selected = False
item.highlighted = False
self._selectedItems = [label]
label.selected = True
elif self._selectionMode == TTkK.MultiSelection:
for item in self._selectedItems:
item.highlighted = False
label.selected = not label.selected
if label.selected:
self._selectedItems.append(label)
else:
self._selectedItems.remove(label)
if label.selected:
self._selectedItems.append(label)
else:
self._selectedItems.remove(label)
if self._highlighted:
self._highlighted.highlighted = False
label.highlighted = True
self._highlighted = label
self.setFocus()
self.textClicked.emit(label.text)
@ -143,8 +162,8 @@ class TTkListWidget(TTkAbstractScrollView):
def addItem(self, item):
if isinstance(item, str):
label = _TTkListWidgetText(text=item, width=max(len(item),self.width()))
label.clicked.connect(self._labelSelectedHandler)
label = TTkAbstractListItem(text=item, width=max(len(item),self.width()))
label.listItemClicked.connect(self._labelSelectedHandler)
return self.addItem(label)
self._items.append(item)
_,y,_,h = self.layout().fullWidgetAreaGeometry()
@ -168,25 +187,27 @@ class TTkListWidget(TTkAbstractScrollView):
self.viewMoveTo(offx, index)
def keyEvent(self, evt):
if not self._highlighted: return
if not self._highlighted: return False
if ( evt.type == TTkK.Character and evt.key==" " ) or \
( evt.type == TTkK.SpecialKey and evt.key == TTkK.Key_Enter ):
if self._highlighted:
self._highlighted.clicked.emit(self._highlighted)
# TTkLog.debug(self._highlighted)
self._highlighted.listItemClicked.emit(self._highlighted)
return True
elif evt.type == TTkK.SpecialKey:
if evt.key == TTkK.Key_Tab:
return False
index = self._items.index(self._highlighted)
offx,offy = self.getViewOffsets()
h = self.height()
if evt.key == TTkK.Key_Up:
index = max(0, index-1)
elif evt.key == TTkK.Key_Down:
index = min(len(self._items)-1, index+1)
elif evt.key == TTkK.Key_PageUp:
index = 0
index = max(0, index-h)
elif evt.key == TTkK.Key_PageDown:
index = len(self._items)-1
index = min(len(self._items)-1, index+h)
elif evt.key == TTkK.Key_Right:
self.viewMoveTo(offx+1, offy)
elif evt.key == TTkK.Key_Left:

61
TermTk/TTkWidgets/menubar.py

@ -28,31 +28,52 @@ from TermTk.TTkCore.log import TTkLog
from TermTk.TTkCore.signal import pyTTkSignal, pyTTkSlot
from TermTk.TTkWidgets.widget import TTkWidget
from TermTk.TTkWidgets.button import TTkButton
from TermTk.TTkWidgets.listwidget import TTkListWidget, TTkAbstractListItem
from TermTk.TTkLayouts.layout import TTkLayout
from TermTk.TTkLayouts.boxlayout import TTkHBoxLayout
class _TTkMenuSpacer(TTkWidget):
__slots__ = ('clicked')
class _TTkMenuListWidget(TTkListWidget):
__slots__ = ('_previous')
def __init__(self, *args, **kwargs):
TTkListWidget.__init__(self, *args, **kwargs)
self._name = kwargs.get('name' , '_TTkMenuListWidget' )
self._previous = kwargs.get('previous',TTkHelper.getFocus())
def keyEvent(self, evt):
if evt.type == TTkK.SpecialKey:
if evt.key == TTkK.Key_Left:
TTkHelper.removeSingleOverlay(self)
if self._previous:
self._previous.setFocus()
return True
elif evt.key == TTkK.Key_Right:
if self._highlighted and \
isinstance(self._highlighted,_TTkMenuButton) and \
self._highlighted._menu:
self._highlighted.menuButtonEvent()
return True
return TTkListWidget.keyEvent(self, evt)
class _TTkMenuSpacer(TTkAbstractListItem):
def __init__(self, *args, **kwargs):
TTkWidget.__init__(self, *args, **kwargs)
TTkAbstractListItem.__init__(self, *args, **kwargs)
self._name = kwargs.get('name' , '_TTkMenuSpacer' )
# Define Signals
self.clicked = pyTTkSignal()
self.resize(1,1)
#self.setMinimumHeight(1)
def paintEvent(self):
TTkLog.debug("pippo")
self._canvas.drawText(pos=(0,0), text="-"*self.width())
class _TTkMenuButton(TTkButton):
__slot__ = ('_color', '_borderColor', '_shortcut', '_menu', 'menuButtonClicked')
class _TTkMenuButton(TTkAbstractListItem):
__slots__ = ('_border', '_borderColor', '_shortcut', '_menu', 'menuButtonClicked')
def __init__(self, *args, **kwargs):
TTkButton.__init__(self, *args, **kwargs)
TTkAbstractListItem.__init__(self, *args, **kwargs)
self._name = kwargs.get('name' , '_TTkMenuButton' )
# signals
self.menuButtonClicked = pyTTkSignal(TTkButton)
self._color = kwargs.get('color', TTkCfg.theme.menuButtonColor )
self._border = kwargs.get('border', TTkCfg.theme.menuButtonColor )
self._borderColor = kwargs.get('borderColor', TTkCfg.theme.menuButtonBorderColor )
self._shortcut = []
self._menu = []
@ -66,7 +87,7 @@ class _TTkMenuButton(TTkButton):
self.resize(txtlen,1)
self.setMinimumSize(txtlen+2,1)
self.setMaximumSize(txtlen+2,1)
self.clicked.connect(self.menuButtonEvent)
self.listItemClicked.connect(self.menuButtonEvent)
def addMenu(self, text):
button = _TTkMenuButton(text=text, borderColor=self._borderColor, border=False)
@ -93,11 +114,11 @@ class _TTkMenuButton(TTkButton):
#self._id = self._list.index(label)
TTkLog.debug(f"Bind Clicked {button._text}")
self.menuButtonClicked.emit(button)
self.setFocus()
TTkHelper.removeOverlay()
self.update()
@pyTTkSlot()
def menuButtonEvent(self):
@pyTTkSlot(TTkAbstractListItem)
def menuButtonEvent(self, listItem=None):
if not self._menu:
self.menuButtonClicked.emit(self)
return
@ -117,20 +138,22 @@ class _TTkMenuButton(TTkButton):
else:
frame = TTkResizableFrame(layout=TTkHBoxLayout(), size=(frameWidth,frameHeight), title=self._text, titleAlign=TTkK.LEFT_ALIGN)
pos = (-1, 0)
listw = TTkList(parent=frame)
menuListWidget = _TTkMenuListWidget()
listw = TTkList(parent=frame, listWidget = menuListWidget)
# listw.textClicked.connect(self._menuCallback)
# listw.textClicked.connect(self._menuCallback)
TTkLog.debug(f"{self._menu}")
for item in self._menu:
listw.addItem(item)
TTkHelper.overlay(self, frame, pos[0], pos[1])
listw.viewport().setFocus()
self.update()
def paintEvent(self):
if self._pressed:
borderColor = self._borderColor
textColor = TTkCfg.theme.menuButtonColorClicked
scColor = TTkCfg.theme.menuButtonShortcutColor
scColor = TTkCfg.theme.menuButtonShortcutColor
else:
borderColor = self._borderColor
textColor = self._color
@ -145,6 +168,12 @@ class _TTkMenuButton(TTkButton):
borderColor=borderColor,
shortcutColor=scColor )
def focusInEvent(self):
self.highlighted=True
def focusOutEvent(self):
self.highlighted=False
class TTkMenuLayout(TTkHBoxLayout):
__slots__ = ('_itemsLeft', '_itemsCenter', '_itemsRight', '_buttons')
def __init__(self, *args, **kwargs):

9
TermTk/TTkWidgets/widget.py

@ -56,7 +56,8 @@ class TTkWidget(TMouseEvents,TKeyEvents):
'_padt', '_padb', '_padl', '_padr',
'_maxw', '_maxh', '_minw', '_minh',
'_focus','_focus_policy',
'_layout', '_canvas', '_visible', '_transparent')
'_layout', '_canvas', '_visible', '_transparent',
'_pendingMouseRelease')
def __init__(self, *args, **kwargs):
'''
@ -92,6 +93,8 @@ class TTkWidget(TMouseEvents,TKeyEvents):
self._name = kwargs.get('name', 'TTkWidget' )
self._parent = kwargs.get('parent', None )
self._pendingMouseRelease = False
self._x = kwargs.get('x', 0 )
self._y = kwargs.get('y', 0 )
self._x, self._y = kwargs.get('pos', (self._x, self._y))
@ -334,6 +337,7 @@ class TTkWidget(TMouseEvents,TKeyEvents):
if evt.evt == TTkK.Release:
#if self.hasFocus():
# self.clearFocus()
self._pendingMouseRelease = False
if self.mouseReleaseEvent(evt):
return True
@ -343,6 +347,7 @@ class TTkWidget(TMouseEvents,TKeyEvents):
self.raiseWidget()
if self.mousePressEvent(evt):
# TTkLog.debug(f"Click {self._name}")
self._pendingMouseRelease = True
return True
if evt.key == TTkK.Wheel:
@ -543,6 +548,7 @@ class TTkWidget(TMouseEvents,TKeyEvents):
self.layoutUpdated()
def setFocus(self):
if self._focus: return
TTkLog.debug(self._name)
tmp = TTkHelper.getFocus()
if tmp == self: return
@ -557,6 +563,7 @@ class TTkWidget(TMouseEvents,TKeyEvents):
self.focusInEvent()
def clearFocus(self):
if not self._focus: return
TTkHelper.clearFocus()
self._focus = False
self.focusOutEvent()

6
TermTk/libbpytop/input.py

@ -58,9 +58,11 @@ class MouseEvent:
self.evt = evt
self.raw = raw
def clone(self, pos=None):
def clone(self, pos=None, evt=None):
x,y = pos if pos != None else (self.x, self.y)
return MouseEvent(x, y, self.key, self.evt, self.raw)
if not evt:
evt = self.evt
return MouseEvent(x, y, self.key, evt, self.raw)
def key2str(self):
return {

4
demo/showcase/menubar.py

@ -49,7 +49,7 @@ def demoMenuBar(root=None):
frameTop.menubarTop().addMenu("X", alignment=ttk.TTkK.RIGHT_ALIGN)
window = ttk.TTkWindow(title="Test MenuBar", parent=frameTop,pos=(1,1), size=(60,10), border=True)
fileMenu2 = window.menubarTop().addMenu("&File")
fileMenu2 = window.menubarTop().addMenu("&Fi&le")
fileMenu2.addMenu("New File")
fileMenu2.addMenu("Old File")
fileMenu2.addSpacer()
@ -69,7 +69,7 @@ def demoMenuBar(root=None):
fileMenu2.addSpacer()
fileMenu2.addMenu("Exit")
editMenu2 = window.menubarTop().addMenu("&Edit")
editMenu2 = window.menubarTop().addMenu("&E&dit")
editMenu2.addMenu("Undo")
editMenu2.addMenu("Redo")
editMenu2.addMenu("Cut")

4
docs/TODO.md

@ -147,6 +147,10 @@
- [x] Events (Signal/Slots)
- [ ] Themes
- [x] Use Spinbox for R G B
#### Date Picker
- [ ] Basic Implementation
- [ ] Events (Signal/Slots)
- [ ] Themes
#### File Picker
- [ ] Basic Implementation
- [ ] Events (Signal/Slots)

Loading…
Cancel
Save