Browse Source

chore(tab): add tab status class and reworked highlighted (#555)

pull/556/head
Pier CeccoPierangioliEugenio 3 months ago committed by GitHub
parent
commit
4ff4c06da4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 3
      demo/showcase/dndtabs.py
  2. 20
      docs/MDNotes/internals/focus.keypress.md
  3. 4
      libs/pyTermTk/TermTk/TTkTheme/draw_ascii.py
  4. 4
      libs/pyTermTk/TermTk/TTkTheme/draw_utf8.py
  5. 21
      libs/pyTermTk/TermTk/TTkWidgets/kodetab.py
  6. 655
      libs/pyTermTk/TermTk/TTkWidgets/tabwidget.py
  7. 595
      tests/pytest/widgets/test_kode_tab.py
  8. 666
      tests/pytest/widgets/test_tab.py
  9. 2
      tests/t.ui/test.ui.012.tab.01.py
  10. 87
      tests/t.ui/test.ui.012.tab.02.py

3
demo/showcase/dndtabs.py

@ -69,9 +69,10 @@ def demoDnDTabs(root=None, border=True):
def main(): def main():
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument('-f', help='Full Screen', action='store_true') parser.add_argument('-f', help='Full Screen', action='store_true')
parser.add_argument('-t', help='Track Mouse', action='store_true')
args = parser.parse_args() args = parser.parse_args()
root = ttk.TTk() root = ttk.TTk(mouseTrack=args.t)
if args.f: if args.f:
rootTab = root rootTab = root
root.setLayout(ttk.TTkGridLayout()) root.setLayout(ttk.TTkGridLayout())

20
docs/MDNotes/internals/focus.keypress.md

@ -58,13 +58,13 @@
# TODO # TODO
[x] - Implement root handler to handle overlay widgets where the focus switch should be contained in the overlay - [x] - Implement root handler to handle overlay widgets where the focus switch should be contained in the overlay
[x] - Remove nextFocus,prevFocus from the helper - [x] - Remove nextFocus,prevFocus from the helper
[ ] - Investigate other widgets focus propagation - [ ] - Investigate other widgets focus propagation
[ ] - Switch Focus to the menu - [ ] - Switch Focus to the menu
[ ] - Type TTkLayout and add docstrings - [ ] - Type TTkLayout and add docstrings
[ ] - Add deprecated methods in ttkhelper - [ ] - Add deprecated methods in ttkhelper
[x] - Investigate lineedit of the combobox - [x] - Investigate lineedit of the combobox
[x] - Tab Widget: Adapt to the new logic - [x] - Tab Widget: Adapt to the new logic
[x] - DateTime: Adapt to the new logic - [x] - DateTime: Adapt to the new logic
[ ] - Tab Widget: Apply Highlight colors - [x] - Tab Widget: Apply Highlight colors

4
libs/pyTermTk/TermTk/TTkTheme/draw_ascii.py

@ -106,7 +106,9 @@ class TTkTheme():
#21 22 23 24 25 26 27 28 29 30 #21 22 23 24 25 26 27 28 29 30
'=','=','\\','/','X','X','=','=','-','X', '=','=','\\','/','X','X','=','=','-','X',
#31 32 33 34 35 36 37 38 39 40 #31 32 33 34 35 36 37 38 39 40
'<','>','|','|','-','-','X' '<','>','|','|','-','-','X','X','X','X',
#41 42 43 44 45
'/','-','-','\\','|',
) )
braille=( braille=(

4
libs/pyTermTk/TermTk/TTkTheme/draw_utf8.py

@ -162,7 +162,9 @@ class TTkTheme():
#21 22 23 24 25 26 27 28 29 30 #21 22 23 24 25 26 27 28 29 30
'','','','','','','','','','X', '','','','','','','','','','X',
#31 32 33 34 35 36 37 38 39 40 #31 32 33 34 35 36 37 38 39 40
'','','','','','','X' '','','','','','','X','X','X','X',
#41 42 43 44 45
'','','','','',
) )
''' Tab Examples ''' Tab Examples

21
libs/pyTermTk/TermTk/TTkWidgets/kodetab.py

@ -22,7 +22,7 @@
__all__ = ['TTkKodeTab'] __all__ = ['TTkKodeTab']
from typing import Callable, Iterator, Tuple, List from typing import Callable, Iterator, Tuple, List, Any
from TermTk.TTkCore.constant import TTkK from TermTk.TTkCore.constant import TTkK
from TermTk.TTkCore.helper import TTkHelper from TermTk.TTkCore.helper import TTkHelper
@ -121,9 +121,6 @@ class _TTkKodeTab(TTkTabWidget):
self.update() self.update()
return True return True
def _dropNewKodeTab(self, y:int, data:_TTkNewTabWidgetDragData) -> bool:
pass
def dropEvent(self, evt:TTkDnDEvent) -> bool: def dropEvent(self, evt:TTkDnDEvent) -> bool:
self._frameOverlay = None self._frameOverlay = None
x,y = evt.x, evt.y x,y = evt.x, evt.y
@ -147,7 +144,7 @@ class _TTkKodeTab(TTkTabWidget):
splitter.setStyle(_splitter_NERD_1_style) splitter.setStyle(_splitter_NERD_1_style)
splitter.addWidget(self) splitter.addWidget(self)
index=offset index=offset
splitter.insertWidget(index+offset, kt:=_TTkKodeTab(baseWidget=self._baseWidget, border=self.border(), barType=self._barType, closable=self.tabsClosable())) splitter.insertWidget(index+offset, kt:=_TTkKodeTab(baseWidget=self._baseWidget, border=self.border(), barType=self._tabStatus.barType, closable=self.tabsClosable()))
kt._dropEventProxy = self._dropEventProxy kt._dropEventProxy = self._dropEventProxy
kt.kodeTabCloseRequested.connect(self._baseWidget._handleKodeTabCloseRequested) kt.kodeTabCloseRequested.connect(self._baseWidget._handleKodeTabCloseRequested)
for (_w,_l) in data: for (_w,_l) in data:
@ -180,7 +177,7 @@ class _TTkKodeTab(TTkTabWidget):
w,h = self.size() w,h = self.size()
h-=3 h-=3
y-=3 y-=3
index = tw._tabBar._tabButtons.index(tb) index = tw._tabStatus.tabButtons.index(tb)
widget = tw._tabWidgets[index] widget = tw._tabWidgets[index]
label = tb.text() label = tb.text()
dropData = [(widget,label)] dropData = [(widget,label)]
@ -210,7 +207,7 @@ class _TTkKodeTab(TTkTabWidget):
def _kodeTabClosed(self, widget=None): def _kodeTabClosed(self, widget=None):
# Remove the widget and/or all the cascade empty splitters # Remove the widget and/or all the cascade empty splitters
fwold = self._baseWidget._getFirstWidget() fwold = self._baseWidget._getFirstWidget()
widget = widget if issubclass(type(widget), _TTkKodeTab) else self widget = widget if isinstance(widget, _TTkKodeTab) else self
if not widget._tabWidgets: if not widget._tabWidgets:
if splitter := widget.parentWidget(): if splitter := widget.parentWidget():
while splitter.count() == 1 and splitter != self._baseWidget: while splitter.count() == 1 and splitter != self._baseWidget:
@ -271,18 +268,18 @@ class TTkKodeTab(TTkSplitter):
return item if type(item)==_TTkKodeTab else None return item if type(item)==_TTkKodeTab else None
def iterItems(self) -> Iterator[Tuple[_TTkKodeTab, int]]: def iterItems(self) -> Iterator[Tuple[_TTkKodeTab, int]]:
def _iterSplitter(split:TTkSplitter): def _iterSplitter(split:TTkSplitter) -> Iterator[Tuple[_TTkKodeTab, int]]:
for i in range(split.count()): for i in range(split.count()):
_wid = split.widget(i) _wid = split.widget(i)
if issubclass(type(_wid), TTkSplitter): if isinstance(_wid, TTkSplitter):
yield from _iterSplitter(_wid) yield from _iterSplitter(_wid)
elif issubclass(type(_wid), _TTkKodeTab): elif isinstance(_wid, _TTkKodeTab):
yield from _wid.iterItems() yield from _wid.iterItems()
yield from _iterSplitter(self) yield from _iterSplitter(self)
def setDropEventProxy(self, proxy:Callable) -> None: def setDropEventProxy(self, proxy:Callable[[TTkDnDEvent], bool]) -> None:
for widget in self.layout().iterWidgets(onlyVisible=False): for widget in self.layout().iterWidgets(onlyVisible=False):
if issubclass(type(widget),_TTkKodeTab): if isinstance(widget, _TTkKodeTab):
widget.setDropEventProxy(proxy) widget.setDropEventProxy(proxy)
return super().setDropEventProxy(proxy) return super().setDropEventProxy(proxy)

655
libs/pyTermTk/TermTk/TTkWidgets/tabwidget.py

File diff suppressed because it is too large Load Diff

595
tests/pytest/widgets/test_kode_tab.py

@ -0,0 +1,595 @@
# MIT License
#
# Copyright (c) 2025 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com>
#
# 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 sys, os
sys.path.append(os.path.join(sys.path[0],'../../../libs/pyTermTk'))
import TermTk as ttk
from TermTk.TTkWidgets.kodetab import _TTkKodeTab
from TermTk.TTkWidgets.tabwidget import _TTkTabWidgetDragData, _TTkNewTabWidgetDragData
from TermTk.TTkGui.drag import TTkDnDEvent
# ============================================================================
# TTkKodeTab Basic Tests
# ============================================================================
def test_kodetab_initialization():
'''
Test that TTkKodeTab initializes correctly.
'''
kodeTab = ttk.TTkKodeTab()
assert kodeTab is not None
assert isinstance(kodeTab, ttk.TTkSplitter)
# Should have at least one internal _TTkKodeTab widget
first_widget = kodeTab._getFirstWidget()
assert first_widget is not None
assert isinstance(first_widget, _TTkKodeTab)
def test_kodetab_add_single_tab():
'''
Test adding a single tab to TTkKodeTab.
'''
kodeTab = ttk.TTkKodeTab()
widget = ttk.TTkWidget()
index = kodeTab.addTab(widget, "Tab 1")
assert index == 0
assert kodeTab._lastKodeTabWidget.count() == 1
assert kodeTab._lastKodeTabWidget.widget(0) == widget
def test_kodetab_add_multiple_tabs():
'''
Test adding multiple tabs to TTkKodeTab.
'''
kodeTab = ttk.TTkKodeTab()
widget1 = ttk.TTkWidget()
widget2 = ttk.TTkWidget()
widget3 = ttk.TTkWidget()
index1 = kodeTab.addTab(widget1, "Tab 1")
index2 = kodeTab.addTab(widget2, "Tab 2")
index3 = kodeTab.addTab(widget3, "Tab 3")
assert index1 == 0
assert index2 == 1
assert index3 == 2
assert kodeTab._lastKodeTabWidget.count() == 3
def test_kodetab_add_tab_with_data():
'''
Test adding tabs with associated data.
'''
kodeTab = ttk.TTkKodeTab()
widget1 = ttk.TTkWidget()
widget2 = ttk.TTkWidget()
kodeTab.addTab(widget1, "Tab 1", data="data1")
kodeTab.addTab(widget2, "Tab 2", data={"key": "value"})
assert kodeTab._lastKodeTabWidget.tabData(0) == "data1"
assert kodeTab._lastKodeTabWidget.tabData(1) == {"key": "value"}
def test_kodetab_set_current_widget():
'''
Test setting the current widget in TTkKodeTab.
'''
kodeTab = ttk.TTkKodeTab()
widget1 = ttk.TTkWidget()
widget2 = ttk.TTkWidget()
widget3 = ttk.TTkWidget()
kodeTab.addTab(widget1, "Tab 1")
kodeTab.addTab(widget2, "Tab 2")
kodeTab.addTab(widget3, "Tab 3")
kodeTab.setCurrentWidget(widget2)
assert kodeTab._lastKodeTabWidget.currentWidget() == widget2
kodeTab.setCurrentWidget(widget3)
assert kodeTab._lastKodeTabWidget.currentWidget() == widget3
def test_kodetab_iter_items():
'''
Test iterating over all tabs in TTkKodeTab.
'''
kodeTab = ttk.TTkKodeTab()
widget1 = ttk.TTkWidget()
widget2 = ttk.TTkWidget()
widget3 = ttk.TTkWidget()
kodeTab.addTab(widget1, "Tab 1")
kodeTab.addTab(widget2, "Tab 2")
kodeTab.addTab(widget3, "Tab 3")
items = list(kodeTab.iterItems())
assert len(items) == 3
for tab_widget, index in items:
assert isinstance(tab_widget, _TTkKodeTab)
assert 0 <= index < tab_widget.count()
def test_kodetab_signals():
'''
Test that TTkKodeTab signals are emitted correctly.
'''
kodeTab = ttk.TTkKodeTab()
current_changed_called = []
tab_clicked_called = []
tab_added_called = []
kodeTab.currentChanged.connect(
lambda tw, i, w, d: current_changed_called.append((tw, i, w, d))
)
kodeTab.tabBarClicked.connect(
lambda tw, i, w, d: tab_clicked_called.append((tw, i, w, d))
)
kodeTab.tabAdded.connect(
lambda tw, i: tab_added_called.append((tw, i))
)
widget1 = ttk.TTkWidget()
widget2 = ttk.TTkWidget()
kodeTab.addTab(widget1, "Tab 1")
assert len(tab_added_called) == 1
assert len(current_changed_called) == 1
kodeTab.addTab(widget2, "Tab 2")
assert len(tab_added_called) == 2
def test_kodetab_close_requested_signal():
'''
Test that kodeTabCloseRequested signal is emitted correctly.
'''
kodeTab = ttk.TTkKodeTab(closable=True)
close_requested_called = []
kodeTab.kodeTabCloseRequested.connect(
lambda tw, i: close_requested_called.append((tw, i))
)
widget1 = ttk.TTkWidget()
widget2 = ttk.TTkWidget()
kodeTab.addTab(widget1, "Tab 1")
kodeTab.addTab(widget2, "Tab 2")
# Simulate close request
kodeTab._lastKodeTabWidget._handleTabCloseRequested(0)
assert len(close_requested_called) == 1
assert close_requested_called[0][1] == 0
# ============================================================================
# TTkKodeTab Remove/Close Tests
# ============================================================================
def test_kodetab_remove_tab():
'''
Test removing tabs from the internal tab widget.
'''
kodeTab = ttk.TTkKodeTab()
widget1 = ttk.TTkWidget()
widget2 = ttk.TTkWidget()
widget3 = ttk.TTkWidget()
kodeTab.addTab(widget1, "Tab 1")
kodeTab.addTab(widget2, "Tab 2")
kodeTab.addTab(widget3, "Tab 3")
assert kodeTab._lastKodeTabWidget.count() == 3
kodeTab._lastKodeTabWidget.removeTab(1)
assert kodeTab._lastKodeTabWidget.count() == 2
assert kodeTab._lastKodeTabWidget.widget(0) == widget1
assert kodeTab._lastKodeTabWidget.widget(1) == widget3
def test_kodetab_remove_all_tabs():
'''
Test removing all tabs triggers cleanup of empty widgets.
'''
kodeTab = ttk.TTkKodeTab()
widget1 = ttk.TTkWidget()
widget2 = ttk.TTkWidget()
kodeTab.addTab(widget1, "Tab 1")
kodeTab.addTab(widget2, "Tab 2")
internal_tab = kodeTab._lastKodeTabWidget
internal_tab.removeTab(0)
internal_tab.removeTab(0)
# Should still have the base internal tab widget
assert kodeTab.count() >= 0
def test_kodetab_kode_tab_closed():
'''
Test _kodeTabClosed cleanup logic.
'''
kodeTab = ttk.TTkKodeTab()
widget1 = ttk.TTkWidget()
kodeTab.addTab(widget1, "Tab 1")
internal_tab = kodeTab._lastKodeTabWidget
# Remove the tab
internal_tab.removeTab(0)
# Trigger cleanup
internal_tab._kodeTabClosed()
# Verify state
assert isinstance(kodeTab._getFirstWidget(), _TTkKodeTab)
# ============================================================================
# TTkKodeTab Drag and Drop Tests
# ============================================================================
def test_kodetab_drag_enter_event():
'''
Test drag enter event handling.
'''
kodeTab = ttk.TTkKodeTab()
widget = ttk.TTkWidget()
kodeTab.addTab(widget, "Tab 1")
internal_tab = kodeTab._lastKodeTabWidget
# Create a mock drag event
evt = TTkDnDEvent(pos=(5,5), data=None)
# Test drag enter
result = internal_tab.dragEnterEvent(evt)
assert result is True
def test_kodetab_drag_leave_event():
'''
Test drag leave event handling.
'''
kodeTab = ttk.TTkKodeTab()
widget = ttk.TTkWidget()
kodeTab.addTab(widget, "Tab 1")
internal_tab = kodeTab._lastKodeTabWidget
internal_tab._frameOverlay = (0, 0, 10, 10)
evt = TTkDnDEvent(pos=(5,5), data=None)
result = internal_tab.dragLeaveEvent(evt)
assert result is True
assert internal_tab._frameOverlay is None
def test_kodetab_drop_event_new_tab_data():
'''
Test dropping new tab data onto TTkKodeTab.
'''
kodeTab = ttk.TTkKodeTab()
widget1 = ttk.TTkWidget()
kodeTab.addTab(widget1, "Tab 1")
internal_tab = kodeTab._lastKodeTabWidget
# Create new tab drag data
new_widget = ttk.TTkWidget()
drag_data = _TTkNewTabWidgetDragData("New Tab", new_widget, data="test_data")
# Create drop event in center (should add to existing tab bar)
evt = TTkDnDEvent(pos=(50,25), data=drag_data)
result = internal_tab.dropEvent(evt)
# Verify drop was handled
assert result in (True, False) # Depends on implementation details
# def test_kodetab_drop_event_tab_widget_data():
# '''
# Test dropping tab from another widget.
# '''
# kodeTab1 = ttk.TTkKodeTab()
# kodeTab2 = ttk.TTkKodeTab()
# widget1 = ttk.TTkWidget()
# widget2 = ttk.TTkWidget()
# kodeTab1.addTab(widget1, "Tab 1")
# kodeTab2.addTab(widget2, "Tab 2")
# internal_tab1 = kodeTab1._lastKodeTabWidget
# internal_tab2 = kodeTab2._lastKodeTabWidget
# # Get the tab button to drag
# button = internal_tab2.tabButton(0)
# # Create drag data
# drag_data = _TTkTabWidgetDragData(button, internal_tab2)
# # Drop in center
# evt = TTkDnDEvent(pos=(50,25), data=drag_data)
# result = internal_tab1.dropEvent(evt)
# # Verify handling occurred
# assert result in (True, False)
def test_kodetab_drop_event_list_of_new_tabs():
'''
Test dropping a list of new tabs.
'''
kodeTab = ttk.TTkKodeTab()
widget1 = ttk.TTkWidget()
kodeTab.addTab(widget1, "Tab 1")
internal_tab = kodeTab._lastKodeTabWidget
# Create list of new tab data
new_widget1 = ttk.TTkWidget()
new_widget2 = ttk.TTkWidget()
drag_data_list = [
_TTkNewTabWidgetDragData("New Tab 1", new_widget1),
_TTkNewTabWidgetDragData("New Tab 2", new_widget2)
]
# Drop in center
evt = TTkDnDEvent(pos=(50,25), data=drag_data_list)
result = internal_tab.dropEvent(evt)
assert result in (True, False)
def test_kodetab_drop_creates_horizontal_split():
'''
Test that dropping on left/right zones creates horizontal splits.
'''
kodeTab = ttk.TTkKodeTab()
widget1 = ttk.TTkWidget()
kodeTab.addTab(widget1, "Tab 1")
internal_tab = kodeTab._lastKodeTabWidget
# Mock size for positioning
internal_tab._size = (100, 50)
new_widget = ttk.TTkWidget()
drag_data = _TTkNewTabWidgetDragData("New Tab", new_widget)
# Drop on left zone (x < w/4)
evt = TTkDnDEvent(pos=(10,25), data=drag_data)
initial_count = kodeTab.count()
result = internal_tab.dropEvent(evt)
# A split may have been created
# Exact behavior depends on implementation
assert kodeTab.count() >= initial_count
def test_kodetab_drop_creates_vertical_split():
'''
Test that dropping on top/bottom zones creates vertical splits.
'''
kodeTab = ttk.TTkKodeTab()
widget1 = ttk.TTkWidget()
kodeTab.addTab(widget1, "Tab 1")
internal_tab = kodeTab._lastKodeTabWidget
# Mock size
internal_tab._size = (100, 50)
new_widget = ttk.TTkWidget()
drag_data = _TTkNewTabWidgetDragData("New Tab", new_widget)
# Drop on top zone (y < h/4, adjusted for tab bar)
evt = TTkDnDEvent(pos=(50,5), data=drag_data)
initial_count = kodeTab.count()
result = internal_tab.dropEvent(evt)
assert kodeTab.count() >= initial_count
def test_kodetab_set_drop_event_proxy():
'''
Test setting drop event proxy propagates to internal widgets.
'''
kodeTab = ttk.TTkKodeTab()
widget = ttk.TTkWidget()
kodeTab.addTab(widget, "Tab 1")
proxy_called = []
def proxy(evt):
proxy_called.append(evt)
return True
kodeTab.setDropEventProxy(proxy)
# Verify proxy is set
internal_tab = kodeTab._lastKodeTabWidget
assert internal_tab._dropEventProxy == proxy
# ============================================================================
# TTkKodeTab Complex Scenarios
# ============================================================================
def test_kodetab_multiple_splits():
'''
Test creating multiple splits through tab operations.
'''
kodeTab = ttk.TTkKodeTab()
widget1 = ttk.TTkWidget()
widget2 = ttk.TTkWidget()
kodeTab.addTab(widget1, "Tab 1")
kodeTab.addTab(widget2, "Tab 2")
# Count all tab items
items_before = list(kodeTab.iterItems())
assert len(items_before) == 2
def test_kodetab_get_first_widget():
'''
Test getting the first internal widget.
'''
kodeTab = ttk.TTkKodeTab()
first = kodeTab._getFirstWidget()
assert isinstance(first, _TTkKodeTab)
assert first._baseWidget == kodeTab
def test_kodetab_has_menu():
'''
Test checking if internal tab has menu.
'''
kodeTab = ttk.TTkKodeTab()
widget = ttk.TTkWidget()
kodeTab.addTab(widget, "Tab 1")
internal_tab = kodeTab._lastKodeTabWidget
# Initially should not have menu
assert internal_tab._hasMenu() is False
def test_kodetab_add_menu():
'''
Test adding menu to TTkKodeTab.
'''
kodeTab = ttk.TTkKodeTab()
widget = ttk.TTkWidget()
kodeTab.addTab(widget, "Tab 1")
# Add a menu item
menu_item = kodeTab.addMenu("File", data="file_data")
assert menu_item is not None
def test_kodetab_bar_type():
'''
Test different bar types for TTkKodeTab.
'''
from TermTk.TTkWidgets.tabwidget import TTkBarType
kodeTab1 = ttk.TTkKodeTab(barType=TTkBarType.DEFAULT_3)
kodeTab2 = ttk.TTkKodeTab(barType=TTkBarType.NERD_1)
assert kodeTab1._barType == TTkBarType.DEFAULT_3
assert kodeTab2._barType == TTkBarType.NERD_1
def test_kodetab_empty_after_all_removals():
'''
Test that TTkKodeTab handles becoming empty gracefully.
'''
kodeTab = ttk.TTkKodeTab()
widget1 = ttk.TTkWidget()
widget2 = ttk.TTkWidget()
kodeTab.addTab(widget1, "Tab 1")
kodeTab.addTab(widget2, "Tab 2")
internal_tab = kodeTab._lastKodeTabWidget
# Remove all tabs
internal_tab.removeTab(0)
internal_tab.removeTab(0)
# Trigger cleanup
internal_tab._kodeTabClosed()
# Should still be in valid state
assert kodeTab._getFirstWidget() is not None
def test_kodetab_paint_child_canvas():
'''
Test that paintChildCanvas handles frame overlay correctly.
'''
kodeTab = ttk.TTkKodeTab()
widget = ttk.TTkWidget()
kodeTab.addTab(widget, "Tab 1")
internal_tab = kodeTab._lastKodeTabWidget
# Set frame overlay
internal_tab._frameOverlay = (10, 10, 50, 30)
# Call paintChildCanvas (should not raise)
try:
internal_tab.paintChildCanvas()
assert True
except Exception as e:
assert False, f"paintChildCanvas raised exception: {e}"
# Clear overlay
internal_tab._frameOverlay = None
internal_tab.paintChildCanvas()
def test_kodetab_drop_invalid_data():
'''
Test that dropping invalid data returns False.
'''
kodeTab = ttk.TTkKodeTab()
widget = ttk.TTkWidget()
kodeTab.addTab(widget, "Tab 1")
internal_tab = kodeTab._lastKodeTabWidget
# Create event with invalid data
evt = TTkDnDEvent(pos=(50,25), data="invalid_data")
result = internal_tab.dropEvent(evt)
# Should not accept invalid data
assert result is False
def test_kodetab_iter_items_after_operations():
'''
Test that iterItems works correctly after add/remove operations.
'''
kodeTab = ttk.TTkKodeTab()
widgets = [ttk.TTkWidget() for _ in range(5)]
for i, widget in enumerate(widgets):
kodeTab.addTab(widget, f"Tab {i}")
items = list(kodeTab.iterItems())
assert len(items) == 5
# Remove some tabs
kodeTab._lastKodeTabWidget.removeTab(2)
kodeTab._lastKodeTabWidget.removeTab(1)
items = list(kodeTab.iterItems())
assert len(items) == 3

666
tests/pytest/widgets/test_tab.py

@ -0,0 +1,666 @@
# MIT License
#
# Copyright (c) 2025 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com>
#
# 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 sys, os
sys.path.append(os.path.join(sys.path[0],'../../../libs/pyTermTk'))
import TermTk as ttk
# ============================================================================
# TTkTabBar Tests
# ============================================================================
def test_tabbar_add_tabs():
'''
Test adding tabs to TTkTabBar using addTab().
Verifies that tabs are added correctly and currentIndex is updated.
'''
tabBar = ttk.TTkTabBar()
assert tabBar.currentIndex() == -1
index0 = tabBar.addTab("Tab 1")
assert index0 == 0
assert tabBar.currentIndex() == 0
index1 = tabBar.addTab("Tab 2", data="data2")
assert index1 == 1
assert tabBar.currentIndex() == 0
index2 = tabBar.addTab("Tab 3")
assert index2 == 2
assert tabBar.currentIndex() == 0
def test_tabbar_insert_tabs():
'''
Test inserting tabs at specific positions in TTkTabBar.
Verifies that tabs are inserted at correct indices and currentIndex is adjusted.
'''
tabBar = ttk.TTkTabBar()
tabBar.addTab("Tab 1")
tabBar.addTab("Tab 2")
tabBar.addTab("Tab 3")
# Insert at beginning
index = tabBar.insertTab(0, "Tab 0")
assert index == 0
assert tabBar.currentIndex() == 1 # Current should shift
# Insert in middle
index = tabBar.insertTab(2, "Tab 1.5")
assert index == 2
assert tabBar.currentIndex() == 1 # Current shouldn't change
def test_tabbar_remove_tabs():
'''
Test removing tabs from TTkTabBar.
Verifies that tabs are removed correctly and currentIndex is adjusted.
'''
tabBar = ttk.TTkTabBar()
tabBar.addTab("Tab 0")
tabBar.addTab("Tab 1")
tabBar.addTab("Tab 2")
tabBar.addTab("Tab 3")
tabBar.setCurrentIndex(2)
assert tabBar.currentIndex() == 2
# Remove tab before current
tabBar.removeTab(0)
assert tabBar.currentIndex() == 1 # Should decrement
# Remove current tab
tabBar.removeTab(1)
assert tabBar.currentIndex() == 0 # Should stay but point to next tab
# Remove last tab
tabBar.removeTab(1)
assert tabBar.currentIndex() == 0
def test_tabbar_tab_data():
'''
Test setting and getting tab data.
'''
tabBar = ttk.TTkTabBar()
tabBar.addTab("Tab 1", data="data1")
tabBar.addTab("Tab 2", data={"key": "value"})
tabBar.addTab("Tab 3")
assert tabBar.tabData(0) == "data1"
assert tabBar.tabData(1) == {"key": "value"}
assert tabBar.tabData(2) is None
# Test setTabData
tabBar.setTabData(2, "new_data")
assert tabBar.tabData(2) == "new_data"
# Test currentData
tabBar.setCurrentIndex(1)
assert tabBar.currentData() == {"key": "value"}
def test_tabbar_current_index():
'''
Test setting and getting current index.
'''
tabBar = ttk.TTkTabBar()
tabBar.addTab("Tab 0")
tabBar.addTab("Tab 1")
tabBar.addTab("Tab 2")
assert tabBar.currentIndex() == 0
tabBar.setCurrentIndex(1)
assert tabBar.currentIndex() == 1
tabBar.setCurrentIndex(2)
assert tabBar.currentIndex() == 2
# Test invalid index (should not change)
tabBar.setCurrentIndex(10)
assert tabBar.currentIndex() == 2
tabBar.setCurrentIndex(-1)
assert tabBar.currentIndex() == 2
def test_tabbar_signals():
'''
Test that signals are emitted correctly.
'''
tabBar = ttk.TTkTabBar()
current_changed_called = []
tab_clicked_called = []
tab_close_called = []
tabBar.currentChanged.connect(lambda i: current_changed_called.append(i))
tabBar.tabBarClicked.connect(lambda i: tab_clicked_called.append(i))
tabBar.tabCloseRequested.connect(lambda i: tab_close_called.append(i))
tabBar.addTab("Tab 0")
assert len(current_changed_called) == 1
assert current_changed_called[0] == 0
tabBar.addTab("Tab 1")
tabBar.setCurrentIndex(1)
assert len(current_changed_called) == 2
assert current_changed_called[1] == 1
def test_tabbar_closable_tabs():
'''
Test closable tabs functionality.
'''
tabBar = ttk.TTkTabBar(closable=True)
assert tabBar.tabsClosable() is True
tabBar.addTab("Tab 0")
tabBar.addTab("Tab 1", closable=False) # Override for this tab
tabBar.addTab("Tab 2")
# Test that tabs can be added with different closable settings
button0 = tabBar.tabButton(0)
button1 = tabBar.tabButton(1)
button2 = tabBar.tabButton(2)
assert button0 is not None
assert button1 is not None
assert button2 is not None
# ============================================================================
# TTkTabWidget Tests
# ============================================================================
def test_tabwidget_add_tabs():
'''
Test adding tabs to TTkTabWidget with widgets.
'''
tabWidget = ttk.TTkTabWidget()
widget0 = ttk.TTkWidget()
widget1 = ttk.TTkWidget()
widget2 = ttk.TTkWidget()
assert tabWidget.count() == 0
assert tabWidget.currentIndex() == -1
index0 = tabWidget.addTab(widget0, "Tab 0")
assert index0 == 0
assert tabWidget.count() == 1
assert tabWidget.currentIndex() == 0
assert widget0.parentWidget() == tabWidget
index1 = tabWidget.addTab(widget1, "Tab 1", data="data1")
assert index1 == 1
assert tabWidget.count() == 2
index2 = tabWidget.addTab(widget2, "Tab 2")
assert index2 == 2
assert tabWidget.count() == 3
def test_tabwidget_insert_tabs():
'''
Test inserting tabs at specific positions.
'''
tabWidget = ttk.TTkTabWidget()
widget0 = ttk.TTkWidget()
widget1 = ttk.TTkWidget()
widget2 = ttk.TTkWidget()
widget3 = ttk.TTkWidget()
tabWidget.addTab(widget0, "Tab 0")
tabWidget.addTab(widget1, "Tab 1")
tabWidget.addTab(widget2, "Tab 2")
# Insert at beginning
index = tabWidget.insertTab(0, widget3, "Tab -1")
assert index == 0
assert tabWidget.count() == 4
assert tabWidget.widget(0) == widget3
assert tabWidget.currentIndex() == 1 # Should shift
def test_tabwidget_remove_tabs():
'''
Test removing tabs from TTkTabWidget.
'''
tabWidget = ttk.TTkTabWidget()
widget0 = ttk.TTkWidget()
widget1 = ttk.TTkWidget()
widget2 = ttk.TTkWidget()
tabWidget.addTab(widget0, "Tab 0")
tabWidget.addTab(widget1, "Tab 1")
tabWidget.addTab(widget2, "Tab 2")
assert tabWidget.count() == 3
tabWidget.removeTab(1)
assert tabWidget.count() == 2
assert tabWidget.widget(0) == widget0
assert tabWidget.widget(1) == widget2
tabWidget.removeTab(0)
assert tabWidget.count() == 1
assert tabWidget.widget(0) == widget2
def test_tabwidget_current_widget():
'''
Test getting and setting current widget.
'''
tabWidget = ttk.TTkTabWidget()
widget0 = ttk.TTkWidget()
widget1 = ttk.TTkWidget()
widget2 = ttk.TTkWidget()
tabWidget.addTab(widget0, "Tab 0")
tabWidget.addTab(widget1, "Tab 1")
tabWidget.addTab(widget2, "Tab 2")
assert tabWidget.currentWidget() == widget0
tabWidget.setCurrentWidget(widget1)
assert tabWidget.currentWidget() == widget1
assert tabWidget.currentIndex() == 1
tabWidget.setCurrentWidget(widget2)
assert tabWidget.currentWidget() == widget2
assert tabWidget.currentIndex() == 2
def test_tabwidget_widget_by_index():
'''
Test accessing widgets by index.
'''
tabWidget = ttk.TTkTabWidget()
widget0 = ttk.TTkWidget()
widget1 = ttk.TTkWidget()
widget2 = ttk.TTkWidget()
tabWidget.addTab(widget0, "Tab 0")
tabWidget.addTab(widget1, "Tab 1")
tabWidget.addTab(widget2, "Tab 2")
assert tabWidget.widget(0) == widget0
assert tabWidget.widget(1) == widget1
assert tabWidget.widget(2) == widget2
assert tabWidget.widget(10) is None
assert tabWidget.widget(-1) is None
def test_tabwidget_index_of():
'''
Test finding index of a widget.
'''
tabWidget = ttk.TTkTabWidget()
widget0 = ttk.TTkWidget()
widget1 = ttk.TTkWidget()
widget2 = ttk.TTkWidget()
widget_not_added = ttk.TTkWidget()
tabWidget.addTab(widget0, "Tab 0")
tabWidget.addTab(widget1, "Tab 1")
tabWidget.addTab(widget2, "Tab 2")
assert tabWidget.indexOf(widget0) == 0
assert tabWidget.indexOf(widget1) == 1
assert tabWidget.indexOf(widget2) == 2
assert tabWidget.indexOf(widget_not_added) == -1
def test_tabwidget_tab_data():
'''
Test tab data in TTkTabWidget.
'''
tabWidget = ttk.TTkTabWidget()
widget0 = ttk.TTkWidget()
widget1 = ttk.TTkWidget()
tabWidget.addTab(widget0, "Tab 0", data="data0")
tabWidget.addTab(widget1, "Tab 1", data={"key": "value"})
assert tabWidget.tabData(0) == "data0"
assert tabWidget.tabData(1) == {"key": "value"}
tabWidget.setTabData(0, "new_data")
assert tabWidget.tabData(0) == "new_data"
assert tabWidget.currentData() == "new_data"
def test_tabwidget_signals():
'''
Test that TTkTabWidget signals are emitted correctly.
'''
tabWidget = ttk.TTkTabWidget()
current_changed_called = []
tab_clicked_called = []
tabWidget.currentChanged.connect(lambda i: current_changed_called.append(i))
tabWidget.tabBarClicked.connect(lambda i: tab_clicked_called.append(i))
widget0 = ttk.TTkWidget()
widget1 = ttk.TTkWidget()
tabWidget.addTab(widget0, "Tab 0")
assert len(current_changed_called) == 1
tabWidget.addTab(widget1, "Tab 1")
tabWidget.setCurrentIndex(1)
assert len(current_changed_called) == 2
assert current_changed_called[1] == 1
def test_tabwidget_widget_visibility():
'''
Test that only the current widget is visible.
'''
tabWidget = ttk.TTkTabWidget()
widget0 = ttk.TTkWidget()
widget1 = ttk.TTkWidget()
widget2 = ttk.TTkWidget()
tabWidget.addTab(widget0, "Tab 0")
tabWidget.addTab(widget1, "Tab 1")
tabWidget.addTab(widget2, "Tab 2")
# Initially all should be hidden (added hidden)
assert widget0.isVisible() is True
assert widget1.isVisible() is False
assert widget2.isVisible() is False
# After setting index, current should be visible
tabWidget.setCurrentIndex(0)
# Note: Visibility is controlled internally, check currentWidget
assert tabWidget.currentWidget() == widget0
tabWidget.setCurrentIndex(1)
assert tabWidget.currentWidget() == widget1
tabWidget.setCurrentIndex(2)
assert tabWidget.currentWidget() == widget2
def test_tabwidget_closable():
'''
Test closable tabs in TTkTabWidget.
'''
tabWidget = ttk.TTkTabWidget(closable=True)
assert tabWidget.tabsClosable() is True
widget0 = ttk.TTkWidget()
widget1 = ttk.TTkWidget()
tabWidget.addTab(widget0, "Tab 0")
tabWidget.addTab(widget1, "Tab 1", closable=False)
# Both tabs should be added
assert tabWidget.count() == 2
def test_tabwidget_remove_all_tabs():
'''
Test removing all tabs from TTkTabWidget.
'''
tabWidget = ttk.TTkTabWidget()
widget0 = ttk.TTkWidget()
widget1 = ttk.TTkWidget()
widget2 = ttk.TTkWidget()
tabWidget.addTab(widget0, "Tab 0")
tabWidget.addTab(widget1, "Tab 1")
tabWidget.addTab(widget2, "Tab 2")
assert tabWidget.count() == 3
tabWidget.removeTab(0)
tabWidget.removeTab(0)
tabWidget.removeTab(0)
assert tabWidget.count() == 0
assert tabWidget.currentIndex() == -1
def test_tabwidget_bar_type():
'''
Test different bar types.
'''
from TermTk.TTkWidgets.tabwidget import TTkBarType
tabWidget1 = ttk.TTkTabWidget(barType=TTkBarType.DEFAULT_3)
tabWidget2 = ttk.TTkTabWidget(barType=TTkBarType.DEFAULT_2)
tabWidget3 = ttk.TTkTabWidget(barType=TTkBarType.NERD_1)
# Just verify they can be created
assert tabWidget1 is not None
assert tabWidget2 is not None
assert tabWidget3 is not None
# ============================================================================
# Drag and Drop Related Tests
# ============================================================================
def test_tabwidget_drag_data_classes():
'''
Test that drag data classes exist and can be instantiated.
'''
from TermTk.TTkWidgets.tabwidget import (
_TTkTabWidgetDragData,
_TTkNewTabWidgetDragData,
_TTkTabBarDragData
)
tabWidget = ttk.TTkTabWidget()
widget = ttk.TTkWidget()
tabWidget.addTab(widget, "Tab 0")
button = tabWidget.tabButton(0)
# Test _TTkTabWidgetDragData
drag_data1 = _TTkTabWidgetDragData(button, tabWidget)
assert drag_data1.tabButton() == button
assert drag_data1.tabWidget() == tabWidget
# Test _TTkNewTabWidgetDragData
new_widget = ttk.TTkWidget()
drag_data2 = _TTkNewTabWidgetDragData("Label", new_widget, data="test", closable=True)
assert drag_data2.label() == "Label"
assert drag_data2.widget() == new_widget
assert drag_data2.data() == "test"
assert drag_data2.closable() is True
# Test _TTkTabBarDragData
tabBar = ttk.TTkTabBar()
tabBar.addTab("Tab")
bar_button = tabBar.tabButton(0)
drag_data3 = _TTkTabBarDragData(bar_button, tabBar)
assert drag_data3.tabButton() == bar_button
assert drag_data3.tabBar() == tabBar
def test_tabbar_tab_button():
'''
Test accessing tab buttons from TTkTabBar.
'''
tabBar = ttk.TTkTabBar()
tabBar.addTab("Tab 0")
tabBar.addTab("Tab 1")
tabBar.addTab("Tab 2")
button0 = tabBar.tabButton(0)
button1 = tabBar.tabButton(1)
button2 = tabBar.tabButton(2)
assert button0 is not None
assert button1 is not None
assert button2 is not None
# Test button text
assert button0.text() == "Tab 0"
assert button1.text() == "Tab 1"
assert button2.text() == "Tab 2"
# Test invalid index
assert tabBar.tabButton(10) is None
assert tabBar.tabButton(-1) is None
def test_tabwidget_tab_button():
'''
Test accessing tab buttons from TTkTabWidget.
'''
tabWidget = ttk.TTkTabWidget()
widget0 = ttk.TTkWidget()
widget1 = ttk.TTkWidget()
tabWidget.addTab(widget0, "Tab 0")
tabWidget.addTab(widget1, "Tab 1")
button0 = tabWidget.tabButton(0)
button1 = tabWidget.tabButton(1)
assert button0 is not None
assert button1 is not None
assert button0.text() == "Tab 0"
assert button1.text() == "Tab 1"
def test_tabbar_multiple_add_remove():
'''
Test multiple add/remove operations to ensure state consistency.
'''
tabBar = ttk.TTkTabBar()
# Add multiple tabs
for i in range(5):
tabBar.addTab(f"Tab {i}")
assert tabBar.currentIndex() == 0
# Remove some tabs
tabBar.removeTab(2)
tabBar.removeTab(1)
# Add more tabs
tabBar.addTab("New Tab 1")
tabBar.addTab("New Tab 2")
# Verify state is consistent
assert tabBar.tabButton(0) is not None
assert tabBar.tabButton(0).text() == "Tab 0"
def test_tabwidget_multiple_add_remove():
'''
Test multiple add/remove operations with widgets.
'''
tabWidget = ttk.TTkTabWidget()
widgets = [ttk.TTkWidget() for _ in range(5)]
# Add all widgets
for i, widget in enumerate(widgets):
tabWidget.addTab(widget, f"Tab {i}")
assert tabWidget.count() == 5
# Remove some
tabWidget.removeTab(2)
tabWidget.removeTab(1)
assert tabWidget.count() == 3
# Add more
new_widget = ttk.TTkWidget()
tabWidget.addTab(new_widget, "New Tab")
assert tabWidget.count() == 4
def test_tabbar_set_current_after_remove():
'''
Test that setting current index works correctly after removing tabs.
'''
tabBar = ttk.TTkTabBar()
tabBar.addTab("Tab 0")
tabBar.addTab("Tab 1")
tabBar.addTab("Tab 2")
tabBar.addTab("Tab 3")
tabBar.setCurrentIndex(3)
assert tabBar.currentIndex() == 3
# Remove current tab
tabBar.removeTab(3)
# Current should be adjusted
assert tabBar.currentIndex() < 3
# Should be able to set to valid index
tabBar.setCurrentIndex(1)
assert tabBar.currentIndex() == 1
def test_tabwidget_parent_relationship():
'''
Test that widgets maintain correct parent relationships when added to tabs.
'''
tabWidget = ttk.TTkTabWidget()
widget0 = ttk.TTkWidget()
widget1 = ttk.TTkWidget()
assert widget0.parentWidget() is None
assert widget1.parentWidget() is None
tabWidget.addTab(widget0, "Tab 0")
assert widget0.parentWidget() == tabWidget
tabWidget.addTab(widget1, "Tab 1")
assert widget1.parentWidget() == tabWidget
# After removal, parent should still be tabWidget (it's in the layout)
tabWidget.removeTab(0)
# Note: The widget may still have tabWidget as parent depending on implementation
def test_tabbar_empty_initialization():
'''
Test that empty TTkTabBar initializes correctly.
'''
tabBar = ttk.TTkTabBar()
assert tabBar.currentIndex() == -1
assert tabBar.tabButton(0) is None
assert tabBar.tabData(0) is None
assert tabBar.currentData() is None
def test_tabwidget_empty_initialization():
'''
Test that empty TTkTabWidget initializes correctly.
'''
tabWidget = ttk.TTkTabWidget()
assert tabWidget.count() == 0
assert tabWidget.currentIndex() == -1
assert tabWidget.widget(0) is None
assert tabWidget.indexOf(ttk.TTkWidget()) == -1

2
tests/t.ui/test.ui.012.tab.py → tests/t.ui/test.ui.012.tab.01.py

@ -24,7 +24,7 @@
import sys, os import sys, os
sys.path.append(os.path.join(sys.path[0],'../..')) sys.path.append(os.path.join(sys.path[0],'../../libs/pyTermTk'))
import TermTk as ttk import TermTk as ttk
ttk.TTkLog.use_default_file_logging() ttk.TTkLog.use_default_file_logging()

87
tests/t.ui/test.ui.012.tab.02.py

@ -0,0 +1,87 @@
#!/usr/bin/env python3
# MIT License
#
# Copyright (c) 2025 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com>
#
# 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 sys, os
sys.path.append(os.path.join(sys.path[0],'../../libs/pyTermTk'))
import TermTk as ttk
root = ttk.TTk(mouseTrack=True)
winTabbed1 = ttk.TTkWindow(parent=root,pos=(0,0), size=(80,20), title="Test Tab 1", border=True, layout=ttk.TTkGridLayout())
tabWidget1 = ttk.TTkTabWidget(parent=winTabbed1, border=True, barType=ttk.TTkBarType.DEFAULT_3)
tabWidget1.addTab(ttk.TTkTestWidgetSizes(border=True, title="Frame1.1"), "Label 1.1")
tabWidget1.addTab(ttk.TTkTestWidgetSizes(border=True, title="Frame1.2"), "Label 1.2")
tabWidget1.addTab(ttk.TTkTestWidget(border=True, title="Frame1.3"), "Label Test 1.3")
tabWidget1.addTab(ttk.TTkTestWidgetSizes(border=True, title="Frame1.4"), "Label 1.4")
tabWidget1.addTab(ttk.TTkTestWidget(border=True, title="Frame1.5"), "Label Test 1.5")
tabWidget1.addTab(ttk.TTkTestWidgetSizes(border=True, title="Frame1.6"), "Label 1.6")
winTabbed2 = ttk.TTkWindow(parent=root,pos=(10,2), size=(80,20), title="Test Tab 2", border=True, layout=ttk.TTkGridLayout())
tabWidget2 = ttk.TTkTabWidget(parent=winTabbed2, border=True, barType=ttk.TTkBarType.DEFAULT_3)
tabWidget2.addTab(ttk.TTkTestWidgetSizes(border=True, title="Frame2.1"), "Label 2.1")
tabWidget2.addTab(ttk.TTkTestWidgetSizes(border=True, title="Frame2.2"), "Label 2.2")
tabWidget2.addTab(ttk.TTkTestWidget(border=True, title="Frame2.3"), "Label Test 2.3")
tabWidget2.addTab(ttk.TTkTestWidgetSizes(border=True, title="Frame2.4"), "Label 2.4")
tabWidget2.addTab(ttk.TTkTestWidget(border=True, title="Frame2.5"), "Label Test 2.5")
tabWidget2.addTab(ttk.TTkTestWidgetSizes(border=True, title="Frame2.6"), "Label 2.6")
tabWidget2.addMenu("Foo")
tabWidget2.addMenu("Bar", ttk.TTkK.RIGHT)
winTabbed3 = ttk.TTkWindow(parent=root,pos=(20,4), size=(80,20), title="Test Tab 3", border=True, layout=ttk.TTkGridLayout())
tabWidget3 = ttk.TTkTabWidget(parent=winTabbed3, border=True, barType=ttk.TTkBarType.DEFAULT_2)
tabWidget3.addTab(ttk.TTkTestWidgetSizes(border=True, title="Frame3.1"), "Label 3.1")
tabWidget3.addTab(ttk.TTkTestWidgetSizes(border=True, title="Frame3.2"), "Label 3.2")
tabWidget3.addTab(ttk.TTkTestWidget(border=True, title="Frame3.3"), "Label Test 3.3")
tabWidget3.addTab(ttk.TTkTestWidgetSizes(border=True, title="Frame3.4"), "Label 3.4")
tabWidget3.addTab(ttk.TTkTestWidget(border=True, title="Frame3.5"), "Label Test 3.5")
tabWidget3.addTab(ttk.TTkTestWidgetSizes(border=True, title="Frame3.6"), "Label 3.6")
winTabbed4 = ttk.TTkWindow(parent=root,pos=(30,6), size=(80,20), title="Test Tab 4", border=True, layout=ttk.TTkGridLayout())
tabWidget4 = ttk.TTkTabWidget(parent=winTabbed4, border=True, barType=ttk.TTkBarType.DEFAULT_2)
tabWidget4.addTab(ttk.TTkTestWidgetSizes(border=True, title="Frame4.1"), "Label 4.1")
tabWidget4.addTab(ttk.TTkTestWidgetSizes(border=True, title="Frame4.2"), "Label 4.2")
tabWidget4.addTab(ttk.TTkTestWidget(border=True, title="Frame4.3"), "Label Test 4.3")
tabWidget4.addTab(ttk.TTkTestWidgetSizes(border=True, title="Frame4.4"), "Label 4.4")
tabWidget4.addTab(ttk.TTkTestWidget(border=True, title="Frame4.5"), "Label Test 4.5")
tabWidget4.addTab(ttk.TTkTestWidgetSizes(border=True, title="Frame4.6"), "Label 4.6")
tabWidget4.addMenu("Baz")
tabWidget4.addMenu("Foo", ttk.TTkK.RIGHT)
winTabbed5 = ttk.TTkWindow(parent=root,pos=(40,8), size=(80,20), title="Test Tab 5", border=True, layout=ttk.TTkGridLayout())
tabWidget5 = ttk.TTkTabWidget(parent=winTabbed5, border=True, barType=ttk.TTkBarType.NERD_1)
tabWidget5.addTab(ttk.TTkTestWidgetSizes(border=True, title="Frame5.1"), "Label 5.1")
tabWidget5.addTab(ttk.TTkTestWidgetSizes(border=True, title="Frame5.2"), "Label 5.2")
tabWidget5.addTab(ttk.TTkTestWidget(border=True, title="Frame5.3"), "Label Test 5.3")
tabWidget5.addTab(ttk.TTkTestWidgetSizes(border=True, title="Frame5.4"), "Label 5.4")
tabWidget5.addTab(ttk.TTkTestWidget(border=True, title="Frame5.5"), "Label Test 5.5")
tabWidget5.addTab(ttk.TTkTestWidgetSizes(border=True, title="Frame5.6"), "Label 5.6")
winLogs = ttk.TTkWindow(parent=root,pos=(45,10), size=(100,30), title="Logs", border=True, layout=ttk.TTkGridLayout())
ttk.TTkLogViewer(parent=winLogs)
winKeys = ttk.TTkWindow(parent=root,pos=(50,15), size=(100,7), title="Key Press", border=True, layout=ttk.TTkGridLayout())
ttk.TTkKeyPressView(parent=winKeys)
root.mainloop()
Loading…
Cancel
Save