Browse Source

Improved TextEdit to support shared documents

pull/49/head
Eugenio Parodi 4 years ago
parent
commit
da2450bdf6
  1. 15
      TermTk/TTkGui/textcursor.py
  2. 2
      TermTk/TTkGui/textdocument.py
  3. 45
      TermTk/TTkWidgets/texedit.py
  4. 19
      demo/showcase/textedit.py

15
TermTk/TTkGui/textcursor.py

@ -162,14 +162,21 @@ class TTkTextCursor():
def toNum(self):
return self.pos | self.line << 16
__slots__ = ('_document', '_properties', '_cID', '_color')
__slots__ = ('_document', '_properties', '_cID', '_color', '_autoChanged')
def __init__(self, *args, **kwargs):
self._color = None
self._cID = 0
self._autoChanged = False
self._properties = [TTkTextCursor._prop(
TTkTextCursor._CP(),
TTkTextCursor._CP())]
self._document = kwargs.get('document',TTkTextDocument())
self._document.contentsChanged.connect(self._documentContentChanged)
def _documentContentChanged(self):
if self._autoChanged: return True
self.cleanCursors()
self.clearSelection()
def setColor(self, color):
self._color = color
@ -333,8 +340,10 @@ class TTkTextCursor():
pp.anchor.pos += diffPos
pp.position.line += diffLine
pp.anchor.line += diffLine
self._autoChanged = True
self._document.contentsChanged.emit()
self._document.contentsChange.emit(l,b,c)
self._autoChanged = False
self._document.cursorPositionChanged.emit(self)
def selectionStart(self):
@ -404,8 +413,10 @@ class TTkTextCursor():
def removeSelectedText(self):
if not self.hasSelection(): return
a,b,c = self._removeSelectedText()
self._autoChanged = True
self._document.contentsChanged.emit()
self._document.contentsChange.emit(a,b,c)
self._autoChanged = False
def applyColor(self, color):
for p in self._properties:
@ -416,8 +427,10 @@ class TTkTextCursor():
pf = 0 if l > selSt.line else selSt.pos
pt = len(line) if l < selEn.line else selEn.pos
self._document._dataLines[l] = line.setColor(color=color, posFrom=pf, posTo=pt)
self._autoChanged = True
self._document.contentsChanged.emit()
self._document.contentsChange.emit(0,0,0)
self._autoChanged = True
def getHighlightedLines(self, fr, to, color):
# Create a list of cursors (filtering out the ones which

2
TermTk/TTkGui/textdocument.py

@ -37,7 +37,7 @@ class TTkTextDocument():
self.cursorPositionChanged = pyTTkSignal(TTkTextCursor)
self.contentsChange = pyTTkSignal(int,int,int) # int line, int linesRemoved, int linesAdded
self.contentsChanged = pyTTkSignal()
text = kwargs.get('text',"")
text = kwargs.get('text'," ")
self._dataLines = [TTkString(t) for t in text.split('\n')]
def lineCount(self):

45
TermTk/TTkWidgets/texedit.py

@ -42,9 +42,9 @@ class _TTkTextEditView(TTkAbstractScrollView):
'_textWrap', '_lineWrapMode', '_lastWrapUsed',
'_replace',
'_readOnly', '_multiCursor',
# Forwarded Methods
'wrapWidth', 'setWrapWidth',
'wordWrapMode', 'setWordWrapMode',
# # Forwarded Methods
# 'wrapWidth', 'setWrapWidth',
# 'wordWrapMode', 'setWordWrapMode',
# Signals
'currentColorChanged'
)
@ -64,22 +64,36 @@ class _TTkTextEditView(TTkAbstractScrollView):
self._multiCursor = True
self._hsize = 0
self._lastWrapUsed = 0
self._textDocument = TTkTextDocument()
self._textCursor = TTkTextCursor(document=self._textDocument)
self._lineWrapMode = TTkK.NoWrap
self._textWrap = TTkTextWrap(document=self._textDocument)
self._textDocument.contentsChanged.connect(self._rewrap)
self._textDocument.cursorPositionChanged.connect(self._cursorPositionChanged)
self._replace = False
self._cursorParams = None
self._textDocument = None
self._textCursor = None
self._textWrap = None
self.setFocusPolicy(TTkK.ClickFocus + TTkK.TabFocus)
self.setDocument(kwargs.get('document', TTkTextDocument()))
def document(self):
return self._textDocument
def setDocument(self, document):
if self._textDocument:
self._textDocument.contentsChanged.disconnect(self._rewrap)
self._textDocument.cursorPositionChanged.disconnect(self._cursorPositionChanged)
self._textWrap.wrapChanged.disconnect(self.update)
self._textDocument = document
self._textCursor = TTkTextCursor(document=self._textDocument)
self._textWrap = TTkTextWrap(document=self._textDocument)
self._textDocument.contentsChanged.connect(self._rewrap)
self._textDocument.cursorPositionChanged.connect(self._cursorPositionChanged)
# Trigger an update when the rewrap happen
self._textWrap.wrapChanged.connect(self.update)
# forward textWrap Methods
self.wrapWidth = self._textWrap.wrapWidth
self.setWrapWidth = self._textWrap.setWrapWidth
self.wordWrapMode = self._textWrap.wordWrapMode
self.setWordWrapMode = self._textWrap.setWordWrapMode
# forward textWrap Methods
def wrapWidth(self, *args, **kwargs): return self._textWrap.wrapWidth(*args, **kwargs)
def setWrapWidth(self, *args, **kwargs): return self._textWrap.setWrapWidth(*args, **kwargs)
def wordWrapMode(self, *args, **kwargs): return self._textWrap.wordWrapMode(*args, **kwargs)
def setWordWrapMode(self, *args, **kwargs): return self._textWrap.setWordWrapMode(*args, **kwargs)
def textCursor(self):
return self._textCursor
@ -130,6 +144,7 @@ class _TTkTextEditView(TTkAbstractScrollView):
def resizeEvent(self, w, h):
if w != self._lastWrapUsed and w>self._textWrap._tabSpaces:
self._textWrap.setWrapWidth(w)
self._lastWrapUsed = w
self._rewrap()
return super().resizeEvent(w,h)
@ -330,6 +345,7 @@ class _TTkTextEditView(TTkAbstractScrollView):
h = self.height()
subLines = self._textWrap._lines[oy:oy+h]
if not subLines: return
outLines = self._textCursor.getHighlightedLines(subLines[0][0], subLines[-1][0], selectColor)
for y, l in enumerate(subLines):
@ -356,7 +372,8 @@ class TTkTextEdit(TTkAbstractScrollArea):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._name = kwargs.get('name' , 'TTkTextEdit' )
self._textEditView = _TTkTextEditView()
if 'parent' in kwargs: kwargs.pop('parent')
self._textEditView = _TTkTextEditView(*args, **kwargs)
# self.setFocusPolicy(self._textEditView.focusPolicy())
# self._textEditView.setFocusPolicy(TTkK.ParentFocus)
self.setViewport(self._textEditView)

19
demo/showcase/textedit.py

@ -47,10 +47,19 @@ 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))])
def demoTextEdit(root=None):
def demoTextEditSecondary(root=None, document=None):
te = ttk.TTkTextEdit(parent=root, document=document)
te.setLineWrapMode(ttk.TTkK.WidgetWidth)
te.setWordWrapMode(ttk.TTkK.WordWrap)
te.setReadOnly(False)
def demoTextEdit(root=None, document=None):
frame = ttk.TTkFrame(parent=root, border=False, layout=ttk.TTkGridLayout())
te = ttk.TTkTextEdit()
# If no document is passed a default one is created,
# In this showcase I want to be able to share the same
# document among 2 textEdit widgets
te = ttk.TTkTextEdit(document=document)
te.setReadOnly(False)
@ -218,7 +227,11 @@ def main():
else:
rootTree = root
root.setLayout(ttk.TTkGridLayout())
demoTextEdit(rootTree)
split = ttk.TTkSplitter(parent=rootTree)
document = ttk.TTkTextDocument()
demoTextEdit(split, document)
demoTextEditSecondary(split, document)
rootTree.layout().addWidget(ttk.TTkKeyPressView(maxHeight=3),1,0)
root.mainloop()
if __name__ == "__main__":

Loading…
Cancel
Save