diff --git a/libs/pyTermTk/TermTk/TTkCore/TTkTerm/term_base.py b/libs/pyTermTk/TermTk/TTkCore/TTkTerm/term_base.py index a08ba7c9..f88f190d 100644 --- a/libs/pyTermTk/TermTk/TTkCore/TTkTerm/term_base.py +++ b/libs/pyTermTk/TermTk/TTkCore/TTkTerm/term_base.py @@ -84,6 +84,7 @@ class TTkTermBase(): CTRL_S = 0x0002 CTRL_Z = 0x0004 CTRL_Q = 0x0008 + CTRL_Y = 0x0010 title: str = "TermTk" width: int = 0 diff --git a/libs/pyTermTk/TermTk/TTkCore/drivers/term_unix.py b/libs/pyTermTk/TermTk/TTkCore/drivers/term_unix.py index 54b07a9d..d6225347 100644 --- a/libs/pyTermTk/TermTk/TTkCore/drivers/term_unix.py +++ b/libs/pyTermTk/TermTk/TTkCore/drivers/term_unix.py @@ -67,6 +67,8 @@ class TTkTerm(TTkTermBase): attr[6][termios.VSUSP]= b'\x1a' if value else 0 if mask & TTkTerm.Sigmask.CTRL_Q: attr[6][termios.VSTART]= b'\x11' if value else 0 + if mask & TTkTerm.Sigmask.CTRL_Y: + attr[6][termios.VDSUSP]= b'\x19' if value else 0 termios.tcsetattr(sys.stdin, termios.TCSADRAIN, attr) TTkTermBase.setSigmask = _setSigmask diff --git a/libs/pyTermTk/TermTk/TTkGui/textdocument.py b/libs/pyTermTk/TermTk/TTkGui/textdocument.py index bb037418..b71dacbb 100644 --- a/libs/pyTermTk/TermTk/TTkGui/textdocument.py +++ b/libs/pyTermTk/TermTk/TTkGui/textdocument.py @@ -152,7 +152,6 @@ class TTkTextDocument(): self.undoCommandAdded = pyTTkSignal() self.modificationChanged = pyTTkSignal(bool) self._backgroundColor = TTkColor.RST - text = text self._dataLines = [TTkString(t) for t in text.split('\n')] self._modified = False # Cumulative changes since the lasrt snapshot @@ -267,10 +266,10 @@ class TTkTextDocument(): self._snapChanged = None def isUndoAvailable(self): - return self._snap and self._snap._prevDiff + return self._snap is not None and self._snap._prevDiff is not None def isRedoAvailable(self): - return self._snap and self._snap._nextDiff + return self._snap is not None and self._snap._nextDiff is not None def hasSnapshots(self): return self._snap is not None diff --git a/libs/pyTermTk/TermTk/TTkWidgets/kodetab.py b/libs/pyTermTk/TermTk/TTkWidgets/kodetab.py index 05773a3a..ec68db45 100644 --- a/libs/pyTermTk/TermTk/TTkWidgets/kodetab.py +++ b/libs/pyTermTk/TermTk/TTkWidgets/kodetab.py @@ -31,7 +31,7 @@ from TermTk.TTkCore.string import TTkString from TermTk.TTkCore.color import TTkColor, TTkColorGradient from TermTk.TTkCore.signal import pyTTkSlot, pyTTkSignal from TermTk.TTkWidgets.widget import TTkWidget -from TermTk.TTkWidgets.tabwidget import TTkTabWidget, _TTkNewTabWidgetDragData, _TTkTabWidgetDragData +from TermTk.TTkWidgets.tabwidget import TTkTabWidget, TTkBarType, _TTkNewTabWidgetDragData, _TTkTabWidgetDragData from TermTk.TTkWidgets.splitter import TTkSplitter from TermTk.TTkWidgets.frame import TTkFrame from TermTk.TTkLayouts.gridlayout import TTkGridLayout @@ -70,7 +70,7 @@ class _TTkKodeTab(TTkTabWidget): def iterWidgets(self): for i in range(self.count()): - yield self.widget(i) + yield self.widget(i), self.tabButton(i) def dragEnterEvent(self, evt:TTkDnDEvent) -> bool: TTkLog.debug(f"Drag Enter") @@ -122,7 +122,7 @@ class _TTkKodeTab(TTkTabWidget): splitter.replaceWidget(index, splitter := TTkSplitter(orientation=orientation)) splitter.addWidget(self) index=offset - splitter.insertWidget(index+offset, kt:=_TTkKodeTab(baseWidget=self._baseWidget, border=self.border(), closable=self.tabsClosable())) + splitter.insertWidget(index+offset, kt:=_TTkKodeTab(baseWidget=self._baseWidget, border=self.border(), barType=self._barType, closable=self.tabsClosable())) kt._dropEventProxy = self._dropEventProxy kt.addTab(widget,label) if fwold!=(fwnew := self._baseWidget._getFirstWidget()) and fwold._hasMenu(): @@ -208,19 +208,22 @@ class _TTkKodeTab(TTkTabWidget): class TTkKodeTab(TTkSplitter): __slots__ = ( - '_lastKodeTabWidget', + '_lastKodeTabWidget', '_barType', # Signals 'currentChanged','tabBarClicked','tabCloseRequested' ) - def __init__(self, **kwargs) -> None: + def __init__(self, + barType:TTkBarType=TTkBarType.NONE, + **kwargs) -> None: self.currentChanged = pyTTkSignal(TTkTabWidget,int,TTkWidget,object) self.tabBarClicked = pyTTkSignal(TTkTabWidget,int,TTkWidget,object) self.tabCloseRequested = pyTTkSignal(TTkTabWidget,int) + self._barType = barType super().__init__(**kwargs|{'layout':TTkGridLayout()}) kwargs.pop('parent',None) kwargs.pop('visible',None) # self.layout().addWidget(splitter := TTkSplitter()) - self._lastKodeTabWidget = _TTkKodeTab(baseWidget=self, **kwargs) + self._lastKodeTabWidget = _TTkKodeTab(baseWidget=self, barType=self._barType, **kwargs) self._lastKodeTabWidget._dropEventProxy = self._dropEventProxy self.addWidget(self._lastKodeTabWidget) diff --git a/libs/pyTermTk/TermTk/TTkWidgets/menubar.py b/libs/pyTermTk/TermTk/TTkWidgets/menubar.py index d79f931f..ff48c1b9 100644 --- a/libs/pyTermTk/TermTk/TTkWidgets/menubar.py +++ b/libs/pyTermTk/TermTk/TTkWidgets/menubar.py @@ -104,7 +104,7 @@ class TTkMenuBarLayout(TTkHBoxLayout): text, shortcuts = text.extractShortcuts() button = TTkMenuBarButton(text=text, data=data, checkable=checkable, checked=checked) for ch in shortcuts: - shortcut = TTkShortcut(key=TTkK.ALT | ord(ch.upper())) + shortcut = TTkShortcut(key=TTkK.CTRL | ord(ch.upper())) shortcut.activated.connect(button.shortcutEvent) self._mbItems(alignment).addWidget(button) self._buttons.append(button) diff --git a/libs/pyTermTk/TermTk/TTkWidgets/tabwidget.py b/libs/pyTermTk/TermTk/TTkWidgets/tabwidget.py index 91a5a6ff..51ec1436 100644 --- a/libs/pyTermTk/TermTk/TTkWidgets/tabwidget.py +++ b/libs/pyTermTk/TermTk/TTkWidgets/tabwidget.py @@ -20,7 +20,9 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -__all__ = ['TTkTabButton', 'TTkTabBar', 'TTkTabWidget'] +__all__ = ['TTkTabButton', 'TTkTabBar', 'TTkTabWidget', 'TTkBarType'] + +from enum import Enum from TermTk.TTkCore.constant import TTkK from TermTk.TTkCore.helper import TTkHelper @@ -44,16 +46,49 @@ from TermTk.TTkWidgets.menubar import TTkMenuBarButton from TermTk.TTkLayouts.boxlayout import TTkHBoxLayout from TermTk.TTkLayouts.gridlayout import TTkGridLayout +class TTkBarType(Enum): + NONE = 0x00 + DEFAULT_3 = 0x01 + DEFAULT_2 = 0x02 + NERD_1 = 0x04 + + def vSize(self) -> int: + return { + TTkBarType.DEFAULT_3:3, + TTkBarType.DEFAULT_2:2, + TTkBarType.NERD_1:1}.get(self,3) + + def offY(self) -> int: + return { + TTkBarType.DEFAULT_3:1, + TTkBarType.DEFAULT_2:0, + TTkBarType.NERD_1:0}.get(self,1) + +_tabGlyphs = { + 'scroller': ['β—€','β–Ά'], + 'border' : { + TTkBarType.DEFAULT_3 : [], + TTkBarType.DEFAULT_2 : [], + TTkBarType.NERD_1 : ['πŸ­›','🭦','🭑','πŸ­–','β•±','β•²'], + } +} + _tabStyle = { - 'default': {'color': TTkColor.fg("#dddd88")+TTkColor.bg("#000044"), + 'default': {'color': TTkColor.fgbg("#dddd88","#000044"), + 'bgColor': TTkColor.fgbg("#000000","#aaaaaa"), 'borderColor': TTkColor.RST, - 'tabOffsetColor': TTkColor.RST}, + 'tabOffsetColor': TTkColor.RST, + 'glyphs':_tabGlyphs}, 'disabled': {'color': TTkColor.fg('#888888'), + 'bgColor': TTkColor.fgbg("#000000","#aaaaaa"), 'borderColor':TTkColor.fg('#888888'), - 'tabOffsetColor': TTkColor.RST}, - 'focus': {'color': TTkColor.fg("#dddd88")+TTkColor.bg("#000044")+TTkColor.BOLD, + 'tabOffsetColor': TTkColor.RST, + 'glyphs':_tabGlyphs}, + 'focus': {'color': TTkColor.fgbg("#dddd88","#000044")+TTkColor.BOLD, + 'bgColor': TTkColor.fgbg("#000000","#aaaaaa"), 'borderColor': TTkColor.fg("#ffff00") + TTkColor.BOLD, - 'tabOffsetColor': TTkColor.RST}, + 'tabOffsetColor': TTkColor.RST, + 'glyphs':_tabGlyphs}, } _tabStyleNormal = { @@ -64,6 +99,9 @@ _tabStyleFocussed = { 'default': {'borderColor': TTkColor.fg("#ffff00") + TTkColor.BOLD}, } + + + class _TTkTabWidgetDragData(): __slots__ = ('_tabButton', '_tabWidget') def __init__(self, b, tw): @@ -92,31 +130,36 @@ class _TTkTabBarDragData(): def tabButton(self): return self._tabButton def tabBar(self): return self._tabBar -class _TTkTabColorButton(TTkContainer): +# class _TTkTabColorButton(TTkContainer): +class _TTkTabColorButton(TTkWidget): classStyle = _tabStyle | { 'hover': {'color': TTkColor.fg("#dddd88")+TTkColor.bg("#000050")+TTkColor.BOLD, 'borderColor': TTkColor.fg("#AAFFFF")+TTkColor.BOLD}, } __slots__ = ( - '_text', '_border', + '_text', '_barType', # Signals 'clicked' ) def __init__(self, *, text:TTkString='', - border:bool=True, + barType:TTkBarType=TTkBarType.DEFAULT_3, **kwargs) -> None: self.clicked = pyTTkSignal() self._text = TTkString(text.replace('\n','')) - self._border = border + self._barType = barType super().__init__(forwardStyle=True, **kwargs) def text(self) -> TTkString: return self._text + def setText(self, text:TTkString) -> None: + self._text = TTkString(text.replace('\n','')) + self.update() + def mouseReleaseEvent(self, evt:TTkMouseEvent) -> bool: self.clicked.emit() return True @@ -133,7 +176,9 @@ class _TTkTabColorButton(TTkContainer): class TTkTabButton(_TTkTabColorButton): '''TTkTabButton''' - __slots__ = ('_data','_sideEnd', '_tabStatus', '_closable', 'closeClicked', '_closeButtonPressed','_data') + __slots__ = ( + '_data','_sideEnd', '_tabStatus', '_closable', + 'closeClicked', '_closeButtonPressed','_data') def __init__(self, *, data:object=None, closable:bool=False, @@ -148,14 +193,9 @@ class TTkTabButton(_TTkTabColorButton): size = self.text().termWidth() + 2 if self._closable: size += 3 - if self._border: - self.resize(size, 3) - self.setMinimumSize(size, 3) - self.setMaximumSize(size, 3) - else: - self.resize(size, 2) - self.setMinimumSize(size, 2) - self.setMaximumSize(size, 2) + self.resize(size, self._barType.vSize()) + self.setMinimumSize(size, self._barType.vSize()) + self.setMaximumSize(size, self._barType.vSize()) self.setFocusPolicy(TTkK.ParentFocus) def data(self): @@ -187,14 +227,16 @@ class TTkTabButton(_TTkTabColorButton): if self._closable and evt.key == TTkK.MidButton: self.closeClicked.emit() return True - if self._closable and y == (1 if self._border else 0) and w-4<=x bool: x,y = evt.x,evt.y w,h = self.size() - if self._closable and y == (1 if self._border else 0) and w-4<=x None: - self._tabButtons = [] + self._tabButtons:list[TTkTabButton] = [] self._currentIndex = -1 self._lastIndex = -1 self._highlighted = -1 self._tabMovable = False self._tabClosable = closable self._sideEnd = TTkK.LEFT | TTkK.RIGHT - self._small = small - self._leftScroller = _TTkTabScrollerButton(border=not self._small,side=TTkK.LEFT) - self._rightScroller = _TTkTabScrollerButton(border=not self._small,side=TTkK.RIGHT) + self._barType = barType + if barType == TTkBarType.NONE: + self._barType = TTkBarType.DEFAULT_2 if small else TTkBarType.DEFAULT_3 + self._leftScroller = _TTkTabScrollerButton(barType=self._barType,side=TTkK.LEFT) + self._rightScroller = _TTkTabScrollerButton(barType=self._barType,side=TTkK.RIGHT) self._leftScroller.clicked.connect( self._moveToTheLeft) self._rightScroller.clicked.connect(self._andMoveToTheRight) @@ -393,7 +492,7 @@ class TTkTabBar(TTkContainer): '''insertTab''' if index <= self._currentIndex: self._currentIndex += 1 - button = TTkTabButton(parent=self, text=label, border=not self._small, closable=self._tabClosable if closable is None else closable, data=data) + button = TTkTabButton(parent=self, text=label, barType=self._barType, closable=self._tabClosable if closable is None else closable, data=data) self._tabButtons.insert(index,button) button.clicked.connect(lambda :self.setCurrentIndex(self._tabButtons.index(button))) button.clicked.connect(lambda :self.tabBarClicked.emit(self._tabButtons.index(button))) @@ -419,6 +518,12 @@ class TTkTabBar(TTkContainer): def currentData(self): return self.tabData(self._currentIndex) + def tabButton(self, index): + '''tabButton''' + if 0 <= index < len(self._tabButtons): + return self._tabButtons[index] + return None + def tabData(self, index): '''tabData''' if 0 <= index < len(self._tabButtons): @@ -520,9 +625,9 @@ class TTkTabBar(TTkContainer): self._updateTabs() def wheelEvent(self, evt:TTkMouseEvent) -> bool: - if evt.evt == TTkK.WHEEL_Up: + if evt.evt in (TTkK.WHEEL_Up,TTkK.WHEEL_Left): self._moveToTheLeft() - else: + elif evt.evt in (TTkK.WHEEL_Down,TTkK.WHEEL_Right): self._andMoveToTheRight() return True @@ -548,15 +653,18 @@ class TTkTabBar(TTkContainer): borderColor = style['borderColor'] w = self.width() tt = TTkCfg.theme.tab - if self._small: + if self._barType == TTkBarType.DEFAULT_2: lse = tt[23] if self._sideEnd & TTkK.LEFT else tt[19] rse = tt[24] if self._sideEnd & TTkK.RIGHT else tt[19] canvas.drawText(pos=(0,1),text=lse + tt[19]*(w-2) + rse, color=borderColor) - else: + elif self._barType == TTkBarType.DEFAULT_3: lse = tt[11] if self._sideEnd & TTkK.LEFT else tt[12] rse = tt[15] if self._sideEnd & TTkK.RIGHT else tt[12] canvas.drawText(pos=(0,2),text=lse + tt[12]*(w-2) + rse, color=borderColor) - + elif self._barType == TTkBarType.NERD_1: + # glyphs = style['glyphs']['border'][self._barType] + canvas.fill(color=style['bgColor']) + # canvas.drawText(pos=(0,0),color=borderColor,text="-x----------------------------------------") ''' β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” @@ -579,7 +687,7 @@ class TTkTabWidget(TTkFrame): '''TTkTabWidget''' classStyle = _tabStyle __slots__ = ( - '_tabBarTopLayout', '_tabBar', '_topLeftLayout', '_topRightLayout', + '_tabBarTopLayout', '_tabBar', '_barType', '_topLeftLayout', '_topRightLayout', '_tabWidgets', '_spacer', # Forward Signals 'currentChanged', 'tabBarClicked', @@ -590,16 +698,22 @@ class TTkTabWidget(TTkFrame): def __init__(self, *, closable:bool=False, + barType:TTkBarType=TTkBarType.NONE, **kwargs) -> None: self._tabWidgets = [] self._tabBarTopLayout = TTkGridLayout() + self._barType = barType super().__init__(forwardStyle=False, **kwargs) - self._tabBar = TTkTabBar(small = not self.border(), closable=closable) + if barType == TTkBarType.NONE: + self._barType = TTkBarType.DEFAULT_3 if self.border() else TTkBarType.DEFAULT_2 + + self._tabBar = TTkTabBar( + barType=self._barType, + closable=closable) self._topLeftLayout = None self._topRightLayout = None - self._tabBarTopLayout.addWidget(self._tabBar,0,1,3 if self.border() else 2,1) self._tabBar.currentChanged.connect(self._tabChanged) self.setFocusPolicy(self._tabBar.focusPolicy()) @@ -608,10 +722,16 @@ class TTkTabWidget(TTkFrame): self._spacer = TTkSpacer(parent=self) self.setLayout(TTkGridLayout()) - if self.border(): + + if self._barType == TTkBarType.DEFAULT_3: + self._tabBarTopLayout.addWidget(self._tabBar,0,1,3,1) self.setPadding(3,1,1,1) - else: + elif self._barType == TTkBarType.DEFAULT_2: + self._tabBarTopLayout.addWidget(self._tabBar,0,1,2,1) self.setPadding(2,0,0,0) + elif self._barType == TTkBarType.NERD_1: + self._tabBarTopLayout.addWidget(self._tabBar,0,1,1,1) + self.setPadding(1,0,0,0) self.rootLayout().addItem(self._tabBarTopLayout) self._tabBarTopLayout.setGeometry(0,0,self._width,self._padt) @@ -640,6 +760,10 @@ class TTkTabWidget(TTkFrame): def count(self) -> int: return len(self._tabWidgets) + def tabButton(self, index): + '''tabButton''' + return self._tabBar.tabButton(index) + def widget(self, index): '''widget''' if 0 <= index < len(self._tabWidgets):