diff --git a/demo/ttkode.01.py b/demo/ttkode.01.py new file mode 100755 index 00000000..74a2e563 --- /dev/null +++ b/demo/ttkode.01.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python3 + +# MIT License +# +# Copyright (c) 2022 Eugenio Parodi +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import argparse +import os +import sys +import time + + +sys.path.append(os.path.join(sys.path[0],'..')) +import TermTk as ttk + +# ttk.TTkFileTree(parent=self, path=".") +class _KolorFrame(ttk.TTkFrame): + __slots__ = ('_fillColor', '_text') + def __init__(self, fillColor=ttk.TTkColor.RST, text:str="", **kwargs): + self._text = text + self._fillColor = fillColor + ttk.TTkFrame.__init__(self, **kwargs) + self.setFocusPolicy(ttk.TTkK.FocusPolicy.ClickFocus) + + def text(self): + return self._text + + def setFillColor(self, color): + self._fillColor = color + + def paintEvent(self, canvas): + w,h = self.size() + for y in range(h): + canvas.drawText(pos=(0,y),text='',width=w,color=self._fillColor) + canvas.drawText(pos=(2,2),text=self._text) + return super().paintEvent(canvas) + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('-f', help='Full Screen', action='store_true') + args = parser.parse_args() + + ttk.TTkTheme.loadTheme(ttk.TTkTheme.NERD) + + root = ttk.TTk(title="ttkode", mouseTrack=True) + layout = ttk.TTkGridLayout() + if args.f: + root.setLayout(layout) + container = root + border = False + else: + container = ttk.TTkWindow( + parent=root,pos=(0,0), size=(100,40), title="pyTermTk Showcase", border=True, layout=layout, + flags = ttk.TTkK.WindowFlag.WindowMaximizeButtonHint | ttk.TTkK.WindowFlag.WindowCloseButtonHint) + border = False + + at = ttk.TTkAppTemplate(parent=container, border=border) + kodeTab = ttk.TTkKodeTab(border=False, barType=ttk.TTkBarType.NERD_1, closable=True) + fileTree = ttk.TTkFileTree(path='.') + + at.setWidget(widget=fileTree, position=at.LEFT, size=15) + at.setWidget(widget=kodeTab, position=at.MAIN) + at.setWidget(widget=ttk.TTkLogViewer(), position=at.BOTTOM, size=3, title="Logs") + + kodeTab.addTab(_KolorFrame(fillColor=ttk.TTkColor.bg("#008800", modifier=ttk.TTkColorGradient(increment=-6)), title=" uno ")," uno ") + kodeTab.addTab(_KolorFrame(fillColor=ttk.TTkColor.bg("#880000", modifier=ttk.TTkColorGradient(increment=-6)), title=" due ")," due ") + kodeTab.addTab(_KolorFrame(fillColor=ttk.TTkColor.bg("#000088", modifier=ttk.TTkColorGradient(increment=-6)), title=" tre ")," tre ") + kodeTab.addTab(_KolorFrame(fillColor=ttk.TTkColor.bg("#888800", modifier=ttk.TTkColorGradient(increment=-6)), title=" quattro ")," quattro ") + kodeTab.addTab(_KolorFrame(fillColor=ttk.TTkColor.bg("#008888", modifier=ttk.TTkColorGradient(increment=-6)), title=" cinque ")," cinque ") + kodeTab.addTab(_KolorFrame(fillColor=ttk.TTkColor.bg("#880088", modifier=ttk.TTkColorGradient(increment=-6)), title=" sei ")," sei ") + # kodeTab.addTab(_KolorFrame(fillColor=ttk.TTkColor.bg("#888888", modifier=ttk.TTkColorGradient(increment=-6)), title=" sette ")," sette ") + # kodeTab.addTab(_KolorFrame(fillColor=ttk.TTkColor.bg("#444444", modifier=ttk.TTkColorGradient(increment= 3)), title=" otto ")," otto ") + + m1 = kodeTab.addMenu('Test1') + m2 = kodeTab.addMenu('Test2') + + m1.addMenu("Open",checkable=True) + m1.addMenu("Save",checkable=True,checked=True) + m1.addMenu("Save as").setDisabled() + + m2.addMenu("m2 Open",checkable=True) + m2.addMenu("m2 Save",checkable=True,checked=True) + m2.addMenu("m2 Save as").setDisabled() + + def _openFile(item): + kt = _KolorFrame( + text=item.path(), + title=item.path(), + fillColor=ttk.TTkColor.bg("#888888", modifier=ttk.TTkColorGradient(increment=-6)),) + kt.focusChanged.connect(lambda _f, _p=item.path() : ttk.TTkLog.debug(f"Focus Changed ({_f}) -> {_p}")) + kodeTab.addTab(kt, 'File') + kodeTab.setCurrentWidget(kt) + for wid in kodeTab.iterWidgets(): + ttk.TTkLog.debug(wid) + kt.setFocus() + + fileTree.fileActivated.connect(_openFile) + + def _reportClose(tab:ttk.TTkTabWidget, num:int): + ttk.TTkLog.debug(f"DEL: {num} - {tab} - {tab.widget(num).text()}") + + kodeTab.tabCloseRequested.connect(_reportClose) + + root.mainloop() + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/demo/ttkode.old.py b/demo/ttkode.old.py deleted file mode 100755 index 8059e0cc..00000000 --- a/demo/ttkode.old.py +++ /dev/null @@ -1,182 +0,0 @@ -#!/usr/bin/env python3 - -# MIT License -# -# Copyright (c) 2022 Eugenio Parodi -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -import argparse -import os -import sys -import time - - -sys.path.append(os.path.join(sys.path[0],'..')) -from TermTk import TTk, TTkLog, TTkHelper -from TermTk import TTkGridLayout, TTkFileTree, TTkWidget, TTkFrame -from TermTk import TTkWindow, TTkColor, TTkColorGradient, TTkRadioButton, TTkSpacer -from TermTk import TTkTheme, TTkK, TTkSplitter, TTkTabWidget - -# TTkFileTree(parent=self, path=".") -class _KolorFrame(TTkFrame): - __slots__ = ('_fillColor') - def __init__(self, *args, **kwargs): - TTkFrame.__init__(self, *args, **kwargs) - self._fillColor = kwargs.get('fillColor', TTkColor.RST) - - def setFillColor(self, color): - self._fillColor = color - - def paintEvent(self, canvas): - w,h = self.size() - for y in range(h): - canvas.drawText(pos=(0,y),text='',width=w,color=self._fillColor) - return super().paintEvent(canvas) - - -class KodeTab(TTkTabWidget): - __slots__ = ('_frameOverlay') - def __init__(self, *args, **kwargs): - TTkTabWidget.__init__(self, *args, **kwargs) - self._frameOverlay = _KolorFrame('visible',False) - self._frameOverlay.setBorderColor(TTkColor.fg("#00FFFF")+TTkColor.bg("#000044")) - self._frameOverlay.setFillColor(TTkColor.bg("#000088", modifier=TTkColorGradient(increment=-3))) - self.rootLayout().addWidget(self._frameOverlay) - - - def dragEnterEvent(self, evt) -> bool: - TTkLog.debug(f"leave") - return True - - def dragLeaveEvent(self, evt) -> bool: - TTkLog.debug(f"leave") - self._frameOverlay.hide() - return True - - def dragMoveEvent(self, evt) -> bool: - x,y = evt.x, evt.y - w,h = self.size() - if y<3: - return super().dragMoveEvent(evt) - h-=3 - y-=3 - if xw*3//4: - self._frameOverlay.show() - self._frameOverlay.resize(w//4,h) - self._frameOverlay.move(w-w//4, 3) - elif yh*3//4: - self._frameOverlay.show() - self._frameOverlay.resize(w,h//4) - self._frameOverlay.move(0, 3+h-h//4) - else: - self._frameOverlay.hide() - return True - - def dropEvent(self, evt) -> bool: - self._frameOverlay.hide() - x,y = evt.x, evt.y - ret = True - data = evt.data() - tb = data.tabButton() - tw = data.tabWidget() - if y<3: - ret = super().dropEvent(evt) - else: - w,h = self.size() - h-=3 - y-=3 - index = tw._tabBar._tabButtons.index(tb) - widget = tw._tabWidgets[index] - - def _processDrop(index, orientation, offset): - tw.removeTab(index) - splitter = self.parentWidget() - index = splitter.indexOf(self) - if splitter.orientation() != orientation: - splitter.replaceWidget(index, splitter := TTkSplitter(orientation=orientation)) - splitter.addWidget(self) - index=offset - splitter.insertWidget(index+offset, kt:=KodeTab()) - kt.addTab(widget,tb.text()) - if xw*3//4: - _processDrop(index, TTkK.HORIZONTAL, 1) - elif yh*3//4: - _processDrop(index, TTkK.VERTICAL, 1) - else: - ret = super().dropEvent(evt) - - # Remove the widget and/or all the cascade empty splitters - if not tw._tabWidgets: - widget = tw - splitter = widget.parentWidget() - while splitter.count() == 1: - widget = splitter - splitter = widget.parentWidget() - splitter.removeWidget(widget) - - return ret - - -def main(): - parser = argparse.ArgumentParser() - parser.add_argument('-f', help='Full Screen', action='store_true') - args = parser.parse_args() - - TTkTheme.loadTheme(TTkTheme.NERD) - - root = TTk(title="ttkode") - layout = TTkGridLayout() - if args.f: - root.setLayout(layout) - container = root - border = False - else: - container = TTkWindow(parent=root,pos=(0,0), size=(100,40), title="pyTermTk Showcase", border=True, layout=layout) - border = True - - splitter = TTkSplitter(parent=container) - splitter.addWidget(fileTree:=TTkFileTree(path='.'), 15) - - hSplitter = TTkSplitter(parent=splitter, orientation=TTkK.HORIZONTAL) - kt = KodeTab(parent=hSplitter) - - kt.addTab(_KolorFrame(fillColor=TTkColor.bg("#008800", modifier=TTkColorGradient(increment=-6)), title="uno"),"uno") - kt.addTab(_KolorFrame(fillColor=TTkColor.bg("#880000", modifier=TTkColorGradient(increment=-6)), title="due"),"due") - kt.addTab(_KolorFrame(fillColor=TTkColor.bg("#000088", modifier=TTkColorGradient(increment=-6)), title="tre"),"tre") - kt.addTab(_KolorFrame(fillColor=TTkColor.bg("#888800", modifier=TTkColorGradient(increment=-6)), title="quattro"),"quattro") - kt.addTab(_KolorFrame(fillColor=TTkColor.bg("#008888", modifier=TTkColorGradient(increment=-6)), title="cinque"),"cinque") - kt.addTab(_KolorFrame(fillColor=TTkColor.bg("#880088", modifier=TTkColorGradient(increment=-6)), title="sei"),"sei") - - root.mainloop() - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/libs/pyTermTk/TermTk/TTkWidgets/kodetab.py b/libs/pyTermTk/TermTk/TTkWidgets/kodetab.py index ec68db45..27baec92 100644 --- a/libs/pyTermTk/TermTk/TTkWidgets/kodetab.py +++ b/libs/pyTermTk/TermTk/TTkWidgets/kodetab.py @@ -37,6 +37,19 @@ from TermTk.TTkWidgets.frame import TTkFrame from TermTk.TTkLayouts.gridlayout import TTkGridLayout from TermTk.TTkGui.drag import TTkDnDEvent +_splitter_NERD_1_style = { + 'default':{ + 'glyphs' : { + TTkK.VERTICAL : ('▃','▃','▃'), + TTkK.HORIZONTAL : ('┇','║','┇') }, + 'color': TTkColor.fgbg("#dddddd","#222222"), + 'borderColor': TTkColor.fg("#8888aa") }, + 'focus':{ + 'color': TTkColor.fgbg("#ffddff","#222222"), + 'borderColor': TTkColor.fg("#8888aa")}, + 'hover':{ + 'borderColor': TTkColor.fg("#aaaa88")} + } class _TTkKodeTab(TTkTabWidget): __slots__ = ( '_frameOverlay','_baseWidget') @@ -119,7 +132,7 @@ class _TTkKodeTab(TTkTabWidget): splitter = self.parentWidget() index = splitter.indexOf(self) if splitter.orientation() != orientation: - splitter.replaceWidget(index, splitter := TTkSplitter(orientation=orientation)) + splitter.replaceWidget(index, splitter := TTkSplitter(orientation=orientation, style=self.parentWidget().classStyle)) splitter.addWidget(self) index=offset splitter.insertWidget(index+offset, kt:=_TTkKodeTab(baseWidget=self._baseWidget, border=self.border(), barType=self._barType, closable=self.tabsClosable())) @@ -219,6 +232,9 @@ class TTkKodeTab(TTkSplitter): self.tabBarClicked = pyTTkSignal(TTkTabWidget,int,TTkWidget,object) self.tabCloseRequested = pyTTkSignal(TTkTabWidget,int) self._barType = barType + + self.classStyle |= _splitter_NERD_1_style + super().__init__(**kwargs|{'layout':TTkGridLayout()}) kwargs.pop('parent',None) kwargs.pop('visible',None) diff --git a/libs/pyTermTk/TermTk/TTkWidgets/splitter.py b/libs/pyTermTk/TermTk/TTkWidgets/splitter.py index 5b16dccc..456af25a 100644 --- a/libs/pyTermTk/TermTk/TTkWidgets/splitter.py +++ b/libs/pyTermTk/TermTk/TTkWidgets/splitter.py @@ -36,11 +36,14 @@ class TTkSplitter(TTkContainer): '''TTkSplitter''' classStyle = { - 'default': {'color': TTkColor.fg("#dddddd")+TTkColor.bg("#222222"), - 'borderColor': TTkColor.RST}, + 'default': {'glyphs' : { + TTkK.VERTICAL : ('╞','═','╡'), + TTkK.HORIZONTAL : ('╥','║','╨') }, + 'color': TTkColor.fgbg("#dddddd","#222222"), + 'borderColor': TTkColor.RST }, 'disabled': {'color': TTkColor.fg('#888888'), 'borderColor':TTkColor.fg('#888888')}, - 'focus': {'color': TTkColor.fg("#ffddff")+TTkColor.bg("#222222"), + 'focus': {'color': TTkColor.fgbg("#ffddff","#222222"), 'borderColor': TTkColor.fg("#ffffaa")} } @@ -440,12 +443,22 @@ class TTkSplitter(TTkContainer): off= 1 canvas.drawBox(pos=(0,0),size=(w,h),color=borderColor) + glyphs = style['glyphs'][self._orientation] if self._orientation == TTkK.HORIZONTAL: for i in self._separators[:-1]: - canvas.drawVLine(pos=(i+off,0), size=h,color=borderColor) + canvas.drawChar(pos=(i+off,0 ), char=glyphs[0], color=borderColor) + canvas.drawChar(pos=(i+off,h-1), char=glyphs[2], color=borderColor) + if h>2: + canvas.fill(pos=(i+off,1),size=(1,h-2), char=glyphs[1], color=borderColor) + + # canvas.drawVLine(pos=(i+off,0), size=h,color=borderColor) else: for i in self._separators[:-1]: - canvas.drawHLine(pos=(0,i+off), size=w,color=borderColor) + canvas.drawChar(pos=(0, i+off), char=glyphs[0], color=borderColor) + canvas.drawChar(pos=(w-1,i+off), char=glyphs[2], color=borderColor) + if w>2: + canvas.fill(pos=(1,i+off),size=(w-2,1), char=glyphs[1], color=borderColor) + # canvas.drawHLine(pos=(0,i+off), size=w,color=borderColor) if self._orientation == TTkK.HORIZONTAL and self._border: for i,t in enumerate(self._titles): diff --git a/libs/pyTermTk/TermTk/TTkWidgets/tabwidget.py b/libs/pyTermTk/TermTk/TTkWidgets/tabwidget.py index 51ec1436..97289c1a 100644 --- a/libs/pyTermTk/TermTk/TTkWidgets/tabwidget.py +++ b/libs/pyTermTk/TermTk/TTkWidgets/tabwidget.py @@ -75,20 +75,16 @@ _tabGlyphs = { _tabStyle = { 'default': {'color': TTkColor.fgbg("#dddd88","#000044"), - 'bgColor': TTkColor.fgbg("#000000","#aaaaaa"), + 'bgColor': TTkColor.fgbg("#000000","#8888aa"), 'borderColor': TTkColor.RST, 'tabOffsetColor': TTkColor.RST, 'glyphs':_tabGlyphs}, 'disabled': {'color': TTkColor.fg('#888888'), - 'bgColor': TTkColor.fgbg("#000000","#aaaaaa"), 'borderColor':TTkColor.fg('#888888'), - 'tabOffsetColor': TTkColor.RST, - 'glyphs':_tabGlyphs}, + 'tabOffsetColor': TTkColor.RST}, 'focus': {'color': TTkColor.fgbg("#dddd88","#000044")+TTkColor.BOLD, - 'bgColor': TTkColor.fgbg("#000000","#aaaaaa"), 'borderColor': TTkColor.fg("#ffff00") + TTkColor.BOLD, - 'tabOffsetColor': TTkColor.RST, - 'glyphs':_tabGlyphs}, + 'tabOffsetColor': TTkColor.RST}, } _tabStyleNormal = { @@ -196,7 +192,7 @@ class TTkTabButton(_TTkTabColorButton): self.resize(size, self._barType.vSize()) self.setMinimumSize(size, self._barType.vSize()) self.setMaximumSize(size, self._barType.vSize()) - self.setFocusPolicy(TTkK.ParentFocus) + self.setFocusPolicy(TTkK.ClickFocus) def data(self): return self._data @@ -236,6 +232,8 @@ class TTkTabButton(_TTkTabColorButton): x,y = evt.x,evt.y w,h = self.size() offY = self._barType.offY() + if parent:=self.parentWidget(): + parent.setFocus() if self._closable and y == offY and w-4<=x