diff --git a/TermTk/TTkCore/TTkTerm/inputkey.py b/TermTk/TTkCore/TTkTerm/inputkey.py index f6382f24..515e4aa7 100644 --- a/TermTk/TTkCore/TTkTerm/inputkey.py +++ b/TermTk/TTkCore/TTkTerm/inputkey.py @@ -89,8 +89,7 @@ def _translate_key(key): "\033[B" : ( TTkK.Key_Down , TTkK.NoModifier ) , "\033[C" : ( TTkK.Key_Right , TTkK.NoModifier ) , "\033[D" : ( TTkK.Key_Left , TTkK.NoModifier ) , - "\033[5~" : ( TTkK.Key_PageUp , TTkK.NoModifier ) , - "\033[6~" : ( TTkK.Key_PageDown , TTkK.NoModifier ) , + "\033[1;2A" : ( TTkK.Key_Up , TTkK.ShiftModifier ) , "\033[1;2B" : ( TTkK.Key_Down , TTkK.ShiftModifier ) , "\033[1;2C" : ( TTkK.Key_Right , TTkK.ShiftModifier ) , @@ -108,6 +107,19 @@ def _translate_key(key): "\033[1;5C" : ( TTkK.Key_Right , TTkK.ControlModifier ) , "\033[1;5D" : ( TTkK.Key_Left , TTkK.ControlModifier ) , + "\033[5~" : ( TTkK.Key_PageUp , TTkK.NoModifier ) , + "\033[6~" : ( TTkK.Key_PageDown , TTkK.NoModifier ) , + "\033[5;2~" : ( TTkK.Key_PageUp , TTkK.ShiftModifier ) , + "\033[6;2~" : ( TTkK.Key_PageDown , TTkK.ShiftModifier ) , + "\033[5;3~" : ( TTkK.Key_PageUp , TTkK.AltModifier ) , + "\033[6;3~" : ( TTkK.Key_PageDown , TTkK.AltModifier ) , + "\033[5;4~" : ( TTkK.Key_PageUp , TTkK.AltModifier | TTkK.ShiftModifier ) , + "\033[6;4~" : ( TTkK.Key_PageDown , TTkK.AltModifier | TTkK.ShiftModifier ) , + "\033[5;5~" : ( TTkK.Key_PageUp , TTkK.ControlModifier ) , + "\033[6;5~" : ( TTkK.Key_PageDown , TTkK.ControlModifier ) , + "\033[5;7~" : ( TTkK.Key_PageUp , TTkK.AltModifier | TTkK.ControlModifier ) , + "\033[6;7~" : ( TTkK.Key_PageDown , TTkK.AltModifier | TTkK.ControlModifier ) , + # Xterm "\033[F" : ( TTkK.Key_End , TTkK.NoModifier ) , "\033[H" : ( TTkK.Key_Home , TTkK.NoModifier ) , @@ -116,6 +128,42 @@ def _translate_key(key): "\033[1~" : ( TTkK.Key_Home , TTkK.NoModifier ) , "\033[2~" : ( TTkK.Key_Insert , TTkK.NoModifier ) , "\033[3~" : ( TTkK.Key_Delete , TTkK.NoModifier ) , + + "\033[1;2F" : ( TTkK.Key_End , TTkK.ShiftModifier ) , + "\033[1;2H" : ( TTkK.Key_Home , TTkK.ShiftModifier ) , + "\033[2;2~" : ( TTkK.Key_Insert , TTkK.ShiftModifier ) , + "\033[3;2~" : ( TTkK.Key_Delete , TTkK.ShiftModifier ) , + + "\033[1;3F" : ( TTkK.Key_End , TTkK.AltModifier ) , + "\033[1;3H" : ( TTkK.Key_Home , TTkK.AltModifier ) , + "\033[2;3~" : ( TTkK.Key_Insert , TTkK.AltModifier ) , + "\033[3;3~" : ( TTkK.Key_Delete , TTkK.AltModifier ) , + + "\033[1;4F" : ( TTkK.Key_End , TTkK.ShiftModifier | TTkK.AltModifier ) , + "\033[1;4H" : ( TTkK.Key_Home , TTkK.ShiftModifier | TTkK.AltModifier ) , + "\033[2;4~" : ( TTkK.Key_Insert , TTkK.ShiftModifier | TTkK.AltModifier ) , + "\033[3;4~" : ( TTkK.Key_Delete , TTkK.ShiftModifier | TTkK.AltModifier ) , + + "\033[1;5F" : ( TTkK.Key_End , TTkK.ControlModifier ) , + "\033[1;5H" : ( TTkK.Key_Home , TTkK.ControlModifier ) , + "\033[2;5~" : ( TTkK.Key_Insert , TTkK.ControlModifier ) , + "\033[3;5~" : ( TTkK.Key_Delete , TTkK.ControlModifier ) , + + "\033[1;6F" : ( TTkK.Key_End , TTkK.ShiftModifier | TTkK.ControlModifier) , + "\033[1;6H" : ( TTkK.Key_Home , TTkK.ShiftModifier | TTkK.ControlModifier) , + "\033[2;6~" : ( TTkK.Key_Insert , TTkK.ShiftModifier | TTkK.ControlModifier) , + "\033[3;6~" : ( TTkK.Key_Delete , TTkK.ShiftModifier | TTkK.ControlModifier) , + + "\033[1;7F" : ( TTkK.Key_End , TTkK.AltModifier | TTkK.ControlModifier) , + "\033[1;7H" : ( TTkK.Key_Home , TTkK.AltModifier | TTkK.ControlModifier) , + "\033[2;7~" : ( TTkK.Key_Insert , TTkK.AltModifier | TTkK.ControlModifier) , + "\033[3;7~" : ( TTkK.Key_Delete , TTkK.AltModifier | TTkK.ControlModifier) , + + "\033[1;8F" : ( TTkK.Key_End , TTkK.ShiftModifier | TTkK.AltModifier | TTkK.ControlModifier) , + "\033[1;8H" : ( TTkK.Key_Home , TTkK.ShiftModifier | TTkK.AltModifier | TTkK.ControlModifier) , + "\033[2;8~" : ( TTkK.Key_Insert , TTkK.ShiftModifier | TTkK.AltModifier | TTkK.ControlModifier) , + "\033[3;8~" : ( TTkK.Key_Delete , TTkK.ShiftModifier | TTkK.AltModifier | TTkK.ControlModifier) , + "\033" : ( TTkK.Key_Escape , TTkK.NoModifier ) , # Function Key "\033OP" : ( TTkK.Key_F1 , TTkK.NoModifier ) , diff --git a/TermTk/TTkGui/textcursor.py b/TermTk/TTkGui/textcursor.py index 1f8ee7e0..8b6d6c71 100644 --- a/TermTk/TTkGui/textcursor.py +++ b/TermTk/TTkGui/textcursor.py @@ -292,6 +292,18 @@ class TTkTextCursor(): def document(self): return self._document + def replaceText(self, text): + # if there is no selection, just select the next n chars till the end of the line + # the newline is not replaced + for p in self._properties: + if not p.hasSelection(): + line = p.position.line + pos = p.position.pos + size = len(self._document._dataLines[line]) + pos = min(size,pos+len(text)) + p.anchor.set(line,pos) + return self.insertText(text) + def insertText(self, text): l,b,c = 0,1,1 if self.hasSelection(): diff --git a/TermTk/TTkWidgets/texedit.py b/TermTk/TTkWidgets/texedit.py index ad00f9a7..a3ddf737 100644 --- a/TermTk/TTkWidgets/texedit.py +++ b/TermTk/TTkWidgets/texedit.py @@ -150,7 +150,7 @@ class _TTkTextEditView(TTkAbstractScrollView): return super().resizeEvent(w,h) def _updateSize(self): - self._hsize = max( len(l) for l in self._textDocument._dataLines ) + self._hsize = max( len(l) for l in self._textDocument._dataLines ) + 1 def viewFullAreaSize(self) -> (int, int): if self.lineWrapMode() == TTkK.NoWrap: @@ -209,7 +209,7 @@ class _TTkTextEditView(TTkAbstractScrollView): # Scroll the area (if required) to include the position x,y _,_,w,h = self.geometry() offx, offy = self.getViewOffsets() - offx = max(min(offx, x),x-w) + offx = max(min(offx, x),x-w+1) offy = max(min(offy, y),y-h+1) self.viewMoveTo(offx, offy) @@ -254,6 +254,14 @@ class _TTkTextEditView(TTkAbstractScrollView): if evt.type == TTkK.SpecialKey: _,_,w,h = self.geometry() + # TODO: Remove this HACK As soon as possible + # Due to the lack of 'INS' key on many laptops + # I emulate this key using + # CTRL + HOME + if evt.key == TTkK.Key_Home and evt.mod==TTkK.ControlModifier: + evt.key = TTkK.Key_Insert + evt.mod = TTkK.NoModifier + moveMode = TTkTextCursor.MoveAnchor if evt.mod==TTkK.ShiftModifier: moveMode = TTkTextCursor.KeepAnchor @@ -315,15 +323,20 @@ class _TTkTextEditView(TTkAbstractScrollView): # Scroll to align to the cursor p = self._textCursor.position() cx, cy = self._textWrap.dataToScreenPosition(p.line, p.pos) + self._updateSize() self._scrolToInclude(cx,cy) self.update() return True else: # Input char - self._textCursor.insertText(evt.key) + if self._replace: + self._textCursor.replaceText(evt.key) + else: + self._textCursor.insertText(evt.key) self._textCursor.movePosition(TTkTextCursor.Right) # Scroll to align to the cursor p = self._textCursor.position() cx, cy = self._textWrap.dataToScreenPosition(p.line, p.pos) + self._updateSize() self._scrolToInclude(cx,cy) self.update() return True diff --git a/demo/showcase/textedit.py b/demo/showcase/textedit.py index bf5ab595..d4162483 100755 --- a/demo/showcase/textedit.py +++ b/demo/showcase/textedit.py @@ -47,6 +47,11 @@ def getWords(n): def getSentence(a,b,i): return ttk.TTkString(" ").join([f"{i} "]+[getWords(random.randint(1,4)) for i in range(0,random.randint(a,b))]) +class superSimpleHorizontalLine(ttk.TTkWidget): + def paintEvent(self): + w,h = self.size() + self._canvas.drawText(pos=(0,h-1), text='┕'+('━'*(w-2))+'┙',color=ttk.TTkColor.fg("#888888")) + def demoTextEditSecondary(root=None, document=None): te = ttk.TTkTextEdit(parent=root, document=document) te.setLineWrapMode(ttk.TTkK.WidgetWidth) @@ -118,7 +123,7 @@ def demoTextEdit(root=None, document=None): fontLayout.addWidget(btn_italic := ttk.TTkButton(border=True, maxSize=(5,3), checkable=True, text=ttk.TTkString( 'a' , ttk.TTkColor.ITALIC) ),1,5) fontLayout.addWidget(btn_underline := ttk.TTkButton(border=True, maxSize=(5,3), checkable=True, text=ttk.TTkString(' a ', ttk.TTkColor.UNDERLINE) ),1,6) fontLayout.addWidget(btn_strikethrough := ttk.TTkButton(border=True, maxSize=(5,3), checkable=True, text=ttk.TTkString(' a ', ttk.TTkColor.STRIKETROUGH)),1,7) - fontLayout.addWidget(ttk.TTkSpacer(),0,10,2,1) + fontLayout.addWidget(superSimpleHorizontalLine(),0,10,2,1) @ttk.pyTTkSlot(ttk.TTkColor) def _currentColorChangedCB(format):