Browse Source

Merge pull request #152 from ceccopierangiolieugenio/CursorRework

the displayed cursor is now a property of the widget.
pull/154/head
Ceccopierangiolieugenio 3 years ago committed by GitHub
parent
commit
2c2647ddde
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 38
      TermTk/TTkCore/helper.py
  2. 12
      TermTk/TTkWidgets/lineedit.py
  3. 37
      TermTk/TTkWidgets/texedit.py
  4. 34
      TermTk/TTkWidgets/widget.py

38
TermTk/TTkCore/helper.py

@ -35,9 +35,10 @@ class TTkHelper:
_updateWidget = set()
_updateBuffer = set()
_mousePos = (0,0)
_cursorPos = [0,0]
_cursorPos = (0,0)
_cursor = False
_cursorType = TTkTerm.Cursor.BLINKING_BLOCK
_cursorWidget = None
class _Overlay():
__slots__ = ('_widget','_prevFocus','_x','_y','_modal')
def __init__(self,x,y,widget,prevFocus,modal):
@ -345,6 +346,30 @@ class TTkHelper:
return TTkHelper.isParent(p, parent)
return False
@staticmethod
def widgetAt(x, y, layout=None):
layout = layout if layout else TTkHelper._rootWidget.rootLayout()
lx,ly,lw,lh =layout.geometry()
lox, loy = layout.offset()
lx,ly,lw,lh = lx+lox, ly+loy, lw-lox, lh-loy
if x<lx or x>=lx+lw or y<ly or y>=lh+ly: return None
x-=lx
y-=ly
for item in reversed(layout.zSortedItems):
if item.layoutItemType() == TTkK.WidgetItem and not item.isEmpty():
widget = item.widget()
if not widget._visible: continue
wx,wy,ww,wh = widget.geometry()
if wx <= x < wx+ww and wy <= y < wy+wh:
return TTkHelper.widgetAt(x-wx, y-wy, widget.rootLayout())
continue
elif item.layoutItemType() == TTkK.LayoutItem:
if (wid:=TTkHelper.widgetAt(x, y, item)):
return wid
return layout.parentWidget()
@staticmethod
def absPos(widget) -> (int,int):
wx, wy = 0,0
@ -433,13 +458,22 @@ class TTkHelper:
TTkTerm.Cursor.hide()
TTkHelper._cursorType = TTkTerm.Cursor.BLINKING_BLOCK
TTkHelper._cursor = False
# TTkHelper._cursorWidget = None
@staticmethod
def moveCursor(widget, x, y):
TTkHelper._cursorWidget = widget
xx, yy = TTkHelper.absPos(widget)
TTkHelper._cursorPos = [xx+x,yy+y]
pos = (xx+x,yy+y)
if TTkHelper._cursorPos == pos:
return
TTkHelper._cursorPos = pos
TTkTerm.push(TTkTerm.Cursor.moveTo(yy+y+1,xx+x+1))
@staticmethod
def cursorWidget():
return TTkHelper._cursorWidget
class Color(TTkTermColor): pass
# Drag and Drop related helper routines

12
TermTk/TTkWidgets/lineedit.py

@ -63,6 +63,7 @@ class TTkLineEdit(TTkWidget):
self.setMaximumHeight(1)
self.setMinimumSize(1,1)
self.setFocusPolicy(TTkK.ClickFocus + TTkK.TabFocus)
self.enableWidgetCursor()
@pyTTkSlot(str)
def setText(self, text, cursorPos=0x1000):
@ -99,12 +100,11 @@ class TTkLineEdit(TTkWidget):
if cursorPos - self._offset < 0:
self._offset = cursorPos
TTkHelper.moveCursor(self,cursorPos-self._offset,0)
if self.hasFocus():
if self._replace:
TTkHelper.showCursor(TTkK.Cursor_Blinking_Block)
else:
TTkHelper.showCursor(TTkK.Cursor_Blinking_Bar)
if self._replace:
self.setWidgetCursor(pos=(cursorPos-self._offset, 0), type=TTkK.Cursor_Blinking_Block)
else:
self.setWidgetCursor(pos=(cursorPos-self._offset, 0), type=TTkK.Cursor_Blinking_Bar)
self.update()
def paintEvent(self, canvas):

37
TermTk/TTkWidgets/texedit.py

@ -30,7 +30,6 @@ from TermTk.TTkCore.constant import TTkK
from TermTk.TTkCore.cfg import TTkCfg
from TermTk.TTkCore.string import TTkString
from TermTk.TTkCore.signal import pyTTkSignal, pyTTkSlot
from TermTk.TTkCore.helper import TTkHelper
from TermTk.TTkGui.clipboard import TTkClipboard
from TermTk.TTkGui.textwrap1 import TTkTextWrap
from TermTk.TTkGui.textcursor import TTkTextCursor
@ -133,7 +132,9 @@ class TTkTextEditView(TTkAbstractScrollView):
self._clipboard = TTkClipboard()
self.setFocusPolicy(TTkK.ClickFocus + TTkK.TabFocus)
self.setDocument(kwargs.get('document', TTkTextDocument()))
self.disableWidgetCursor(self._readOnly)
self._updateSize()
self.viewChanged.connect(self._pushCursor)
def multiLine(self) -> bool :
'''multiline'''
@ -225,6 +226,7 @@ class TTkTextEditView(TTkAbstractScrollView):
def setReadOnly(self, ro):
self._readOnly = ro
self.disableWidgetCursor(ro)
def clear(self):
self.setText(TTkString())
@ -334,8 +336,6 @@ class TTkTextEditView(TTkAbstractScrollView):
return self.size()
def _pushCursor(self):
if self._readOnly or not self.hasFocus():
return
ox, oy = self.getViewOffsets()
x,y = self._textWrap.dataToScreenPosition(
@ -344,23 +344,13 @@ class TTkTextEditView(TTkAbstractScrollView):
y -= oy
x -= ox
if x > self.width() or y>=self.height() or \
x<0 or y<0:
TTkHelper.hideCursor()
return
# Avoid the show/move cursor to be called again if in the same position
if self._cursorParams and \
self._cursorParams['pos'] == (x,y) and \
self._cursorParams['replace'] == self._replace:
return
self._cursorParams = {'pos': (x,y), 'replace': self._replace}
TTkHelper.moveCursor(self,x,y)
if self._replace:
TTkHelper.showCursor(TTkK.Cursor_Blinking_Block)
self.setWidgetCursor(pos=(x,y), type=TTkK.Cursor_Blinking_Block)
else:
TTkHelper.showCursor(TTkK.Cursor_Blinking_Bar)
self.setWidgetCursor(pos=(x,y), type=TTkK.Cursor_Blinking_Bar)
self.update()
def _setCursorPos(self, x, y, moveAnchor=True, addCursor=False):
@ -389,6 +379,7 @@ class TTkTextEditView(TTkAbstractScrollView):
ox, oy = self.getViewOffsets()
self._setCursorPos(evt.x + ox, evt.y + oy, addCursor=evt.mod&TTkK.ControlModifier==TTkK.ControlModifier)
self._textCursor.clearColor()
self._pushCursor()
self.update()
return True
@ -404,6 +395,7 @@ class TTkTextEditView(TTkAbstractScrollView):
x,y = self._setCursorPos(evt.x + ox, evt.y + oy, moveAnchor=False)
self._textCursor.clearColor()
self._scrolToInclude(x,y)
self._pushCursor()
self.update()
return True
@ -414,6 +406,7 @@ class TTkTextEditView(TTkAbstractScrollView):
if self._textCursor.hasSelection():
self.copy()
self._textCursor.clearColor()
self._pushCursor()
self.update()
return True
@ -424,6 +417,7 @@ class TTkTextEditView(TTkAbstractScrollView):
if self._textCursor.hasSelection():
self.copy()
self._textCursor.clearColor()
self._pushCursor()
self.update()
return True
@ -536,6 +530,7 @@ class TTkTextEditView(TTkAbstractScrollView):
cx, cy = self._textWrap.dataToScreenPosition(p.line, p.pos)
self._updateSize()
self._scrolToInclude(cx,cy)
self._pushCursor()
self.update()
return True
else: # Input char
@ -549,17 +544,12 @@ class TTkTextEditView(TTkAbstractScrollView):
cx, cy = self._textWrap.dataToScreenPosition(p.line, p.pos)
self._updateSize()
self._scrolToInclude(cx,cy)
self._pushCursor()
self.update()
return True
return super().keyEvent(evt)
def focusInEvent(self):
self.update()
def focusOutEvent(self):
TTkHelper.hideCursor()
def paintEvent(self, canvas):
ox, oy = self.getViewOffsets()
if self.hasFocus():
@ -578,7 +568,6 @@ class TTkTextEditView(TTkAbstractScrollView):
if self._lineWrapMode == TTkK.FixedWidth:
canvas.drawVLine(pos=(self._textWrap._wrapWidth,0), size=h, color=TTkCfg.theme.treeLineColor)
self._pushCursor()
class TTkTextEdit(TTkAbstractScrollArea):
'''TTkTextEdit

34
TermTk/TTkWidgets/widget.py

@ -114,6 +114,7 @@ class TTkWidget(TMouseEvents,TKeyEvents, TDragEvents):
'_enabled',
'_lookAndFeel', '_style', '_currentStyle',
'_toolTip',
'_widgetCursor', '_widgetCursorEnabled', '_widgetCursorType',
#Signals
'focusChanged', 'sizeChanged')
@ -123,6 +124,10 @@ class TTkWidget(TMouseEvents,TKeyEvents, TDragEvents):
self.sizeChanged = pyTTkSignal(int,int)
# self.sizeChanged.connect(self.resizeEvent)
self._widgetCursor = (0,0)
self._widgetCursorEnabled = False
self._widgetCursorType = TTkK.Cursor_Blinking_Bar
self._name = kwargs.get('name', self.__class__.__name__)
self._parent = kwargs.get('parent', None )
@ -676,6 +681,7 @@ class TTkWidget(TMouseEvents,TKeyEvents, TDragEvents):
self._focus = True
self.focusChanged.emit(self._focus)
self.focusInEvent()
self._pushWidgetCursor()
def clearFocus(self):
# TTkLog.debug(f"clearFocus: {self._name} - {self._focus}")
@ -805,3 +811,31 @@ class TTkWidget(TMouseEvents,TKeyEvents, TDragEvents):
self.update()
return True
return False
# Widget Cursor Helpers
def enableWidgetCursor(self, enable=True):
self._widgetCursorEnabled = enable
self._pushWidgetCursor()
def disableWidgetCursor(self, disable=True):
self._widgetCursorEnabled = not disable
self._pushWidgetCursor()
def setWidgetCursor(self, pos=None, type=None):
self._widgetCursor = pos if pos else self._widgetCursor
self._widgetCursorType = type if type else self._widgetCursorType
self._pushWidgetCursor()
def _pushWidgetCursor(self):
if self._widgetCursorEnabled and self._visible and ( self._focus or self == TTkHelper.cursorWidget() ):
cx,cy = self._widgetCursor
ax, ay = TTkHelper.absPos(self)
if ( self == TTkHelper.widgetAt(cx+ax, cy+ay) or
# Since the blinking bar can be placed also at the left side of the next
# char, it can be displayed also if its position is one char outside the boudaries
( self._widgetCursorType == TTkK.Cursor_Blinking_Bar and
self == TTkHelper.widgetAt(cx+ax-1, cy+ay) ) ):
TTkHelper.showCursor(self._widgetCursorType)
TTkHelper.moveCursor(self, cx, cy)
else:
TTkHelper.hideCursor()

Loading…
Cancel
Save