Browse Source

TTkTextCursor: contentsChange reports the exact rem/added lines in insertText

pull/64/head
Eugenio Parodi 3 years ago
parent
commit
db4d4e684c
  1. 3
      Makefile
  2. 76
      TermTk/TTkGui/textcursor.py
  3. 3
      TermTk/TTkGui/textdocument.py
  4. 4
      demo/showcase/textedit.py
  5. 35
      tests/pytest/test_002_textedit.py

3
Makefile

@ -95,4 +95,5 @@ test: .venv
tools/check.import.sh
. .venv/bin/activate ; \
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics --exclude .venv,build,tmp ; \
pytest tests/pytest/test_001_demo.py
pytest tests/pytest/test_002_textedit.py ; \
pytest tests/pytest/test_001_demo.py ;

76
TermTk/TTkGui/textcursor.py

@ -327,16 +327,75 @@ class TTkTextCursor():
p.anchor.set(line,pos)
return self.insertText(text)
# I need this moethod to cover the math of merging
# multiples retuen values to be used in the contentsChange
# method
#
# ┬ ┬ ┬ ┬
# x2 -│----│-----l2 ┬┼----┼┐
# x1 l1 ┬┼----┼┐ ││ ││
# ││ ││ a1 r2 ││ ││ a2
# ││ /┼┘-------││-. ││
# r1 ││ /.│--------└┼-.. ││
# ││ /. │ │ \.││-z1
# y1 └┼'. /┴ ┴-. -┼┘-z2
# y2 _│. / \ │
# │ / -┴
# ┴'
#
# x1 = l1
# x2 = l2
# y1 = l1+r1
# y2 = l2+r2 + (r1-a1)
# z1 = l1+a1 + (a2-r2)
# z2 = l2+a2
@staticmethod
def _mergeChangesSlices(ch1,ch2):
l1,r1,a1 = ch1
l2,r2,a2 = ch2
x1 = l1
x2 = l2
y1 = l1+r1
y2 = l2+r2 + (r1-a1)
z1 = l1+a1 + (a2-r2)
z2 = l2+a2
a = min(x1,x2)
b = max(y1,y2) - a
c = max(z1,z2) - a
return a,b,c
def insertText(self, text):
l,b,c = 0,1,1
_lineFirst = -1
if self.hasSelection():
l,b,c = self._removeSelectedText()
# Check if the number of lines is the same as the cursor
_lineFirst, _lineRem, _lineAdd = self._removeSelectedText()
lineFirst = self._properties[0].position.line
lineRem, lineAdd = 0,0
# Check if the number of lines is the same as the number of cursors
# this is a corner case where each line belongs to a
# different cursor
textLines = text.split('\n')
textLines = text.split('\n') if len(text)>1 else text
if len(textLines) != len(self._properties):
textLines = [text]*len(self._properties)
# Calc the added and removed lines
for i, pr in enumerate(self._properties):
lenNewLines=len(textLines[i].split('\n'))
l = pr.position.line
if textLines[i] == '\n':
lineAdd += 1 + l-lineFirst-lineRem
lineRem = l - lineFirst
elif (lineFirst + lineRem) > l:
lineAdd += lenNewLines-1
else:
lineAdd += lenNewLines + l-lineFirst-lineRem
lineRem = l - lineFirst + 1
if _lineFirst != -1:
lineFirst, lineRem, lineAdd = TTkTextCursor._mergeChangesSlices(
(_lineFirst, _lineRem, _lineAdd),
( lineFirst, lineRem, lineAdd))
for i, pr in enumerate(self._properties):
text=textLines[i]
l = pr.position.line
@ -348,11 +407,12 @@ class TTkTextCursor():
if isinstance(ttktext, str):
ttktext = TTkString(text, color)
newLines = (self._document._dataLines[l].substring(to=p) + ttktext + self._document._dataLines[l].substring(fr=p)).split('\n')
newLines = ( self._document._dataLines[l].substring(to=p) +
ttktext +
self._document._dataLines[l].substring(fr=p) ).split('\n')
self._document._dataLines[l] = newLines[0]
for nl in reversed(newLines[1:]):
self._document._dataLines.insert(l+1, nl)
c+=1
# 2 scenarios:
# 1) No Newline(s) added
@ -385,7 +445,7 @@ class TTkTextCursor():
self._autoChanged = True
self._document._changed = True
self._document.contentsChanged.emit()
self._document.contentsChange.emit(l,b,c)
self._document.contentsChange.emit(lineFirst, lineRem, lineAdd)
self._autoChanged = False
self._document.cursorPositionChanged.emit(self)
@ -511,7 +571,7 @@ class TTkTextCursor():
self._autoChanged = True
self._document._changed = True
self._document.contentsChanged.emit()
self._document.contentsChange.emit(0,0,0)
# self._document.contentsChange.emit(0,0,0)
self._autoChanged = True
def getHighlightedLines(self, fr, to, color):

3
TermTk/TTkGui/textdocument.py

@ -144,12 +144,13 @@ class TTkTextDocument():
return sum([len[x] for x in self._dataLines])+self.lineCount()
def setText(self, text):
remLines = len(self._dataLines)
self._dataLines = [TTkString(t) for t in text.split('\n')]
self._changed = False
self._lastSnap = self._dataLines.copy()
self._snap = TTkTextDocument._snapshot(self._lastCursor, None, None)
self.contentsChanged.emit()
self.contentsChange.emit(0,0,len(self._dataLines))
self.contentsChange.emit(0,remLines,len(self._dataLines))
def appendText(self, text):
if type(text) == str:

4
demo/showcase/textedit.py

@ -53,10 +53,12 @@ class superSimpleHorizontalLine(ttk.TTkWidget):
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 = ttk.TTkTextEdit(parent=root, document=document, lineNumber=True)
te.setLineWrapMode(ttk.TTkK.WidgetWidth)
te.setWordWrapMode(ttk.TTkK.WordWrap)
te.setReadOnly(False)
# print the document events for debugging purposes
document.contentsChange.connect(lambda line,rem,add: ttk.TTkLog.debug(f"{line=} {rem=} {add=}"))
def demoTextEdit(root=None, document=None):
frame = ttk.TTkFrame(parent=root, border=False, layout=ttk.TTkGridLayout())

35
tests/pytest/test_002_textedit.py

@ -83,7 +83,7 @@ def test_demo1():
# __........
# rem=8 add=5
def test_demo1():
def test_demo2():
doc = ttk.TTkTextDocument(text=txt)
cur = ttk.TTkTextCursor(document=doc)
@ -107,3 +107,36 @@ def test_demo1():
assert cbLine == 0
assert cbRem == 8
assert cbAdd == 5
# ..........
# __..__..__
# __..______
# __........
# ..........
# ..__......
# ..........
# rem=5 add=3
def test_demo3():
doc = ttk.TTkTextDocument(text=txt)
cur = ttk.TTkTextCursor(document=doc)
_setCursor(cur, [
((1,0),(1,2)),
((1,4),(1,6)),
((1,8),(2,2)),
((2,4),(3,2)),
((5,2),(5,4))])
cbLine, cbRem, cbAdd = -1,-1,-1
def _cb(a,b,c):
nonlocal cbLine, cbRem, cbAdd
cbLine, cbRem, cbAdd = a,b,c
doc.contentsChange.connect(_cb)
cur.removeSelectedText()
print(f"{cbLine=}, {cbRem=}, {cbAdd=}")
assert cbLine == 1
assert cbRem == 5
assert cbAdd == 3
Loading…
Cancel
Save