diff --git a/TermTk/TTkGui/textcursor.py b/TermTk/TTkGui/textcursor.py index 0cabc4fb..1f8ee7e0 100644 --- a/TermTk/TTkGui/textcursor.py +++ b/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 diff --git a/TermTk/TTkGui/textdocument.py b/TermTk/TTkGui/textdocument.py index 7a09fb74..e291dc90 100644 --- a/TermTk/TTkGui/textdocument.py +++ b/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): diff --git a/TermTk/TTkWidgets/texedit.py b/TermTk/TTkWidgets/texedit.py index a0490fa4..ad00f9a7 100644 --- a/TermTk/TTkWidgets/texedit.py +++ b/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) diff --git a/demo/showcase/textedit.py b/demo/showcase/textedit.py index 16fc4599..bf5ab595 100755 --- a/demo/showcase/textedit.py +++ b/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__":