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. 647
      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():
parser = argparse.ArgumentParser()
parser.add_argument('-f', help='Full Screen', action='store_true')
parser.add_argument('-t', help='Track Mouse', action='store_true')
args = parser.parse_args()
root = ttk.TTk()
root = ttk.TTk(mouseTrack=args.t)
if args.f:
rootTab = root
root.setLayout(ttk.TTkGridLayout())

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

@ -58,13 +58,13 @@
# TODO
[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
[ ] - Investigate other widgets focus propagation
[ ] - Switch Focus to the menu
[ ] - Type TTkLayout and add docstrings
[ ] - Add deprecated methods in ttkhelper
[x] - Investigate lineedit of the combobox
[x] - Tab Widget: Adapt to the new logic
[x] - DateTime: Adapt to the new logic
[ ] - Tab Widget: Apply Highlight colors
- [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
- [ ] - Investigate other widgets focus propagation
- [ ] - Switch Focus to the menu
- [ ] - Type TTkLayout and add docstrings
- [ ] - Add deprecated methods in ttkhelper
- [x] - Investigate lineedit of the combobox
- [x] - Tab Widget: Adapt to the new logic
- [x] - DateTime: Adapt to the new logic
- [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
'=','=','\\','/','X','X','=','=','-','X',
#31 32 33 34 35 36 37 38 39 40
'<','>','|','|','-','-','X'
'<','>','|','|','-','-','X','X','X','X',
#41 42 43 44 45
'/','-','-','\\','|',
)
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
'','','','','','','','','','X',
#31 32 33 34 35 36 37 38 39 40
'','','','','','','X'
'','','','','','','X','X','X','X',
#41 42 43 44 45
'','','','','',
)
''' Tab Examples

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

@ -22,7 +22,7 @@
__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.helper import TTkHelper
@ -121,9 +121,6 @@ class _TTkKodeTab(TTkTabWidget):
self.update()
return True
def _dropNewKodeTab(self, y:int, data:_TTkNewTabWidgetDragData) -> bool:
pass
def dropEvent(self, evt:TTkDnDEvent) -> bool:
self._frameOverlay = None
x,y = evt.x, evt.y
@ -147,7 +144,7 @@ class _TTkKodeTab(TTkTabWidget):
splitter.setStyle(_splitter_NERD_1_style)
splitter.addWidget(self)
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.kodeTabCloseRequested.connect(self._baseWidget._handleKodeTabCloseRequested)
for (_w,_l) in data:
@ -180,7 +177,7 @@ class _TTkKodeTab(TTkTabWidget):
w,h = self.size()
h-=3
y-=3
index = tw._tabBar._tabButtons.index(tb)
index = tw._tabStatus.tabButtons.index(tb)
widget = tw._tabWidgets[index]
label = tb.text()
dropData = [(widget,label)]
@ -210,7 +207,7 @@ class _TTkKodeTab(TTkTabWidget):
def _kodeTabClosed(self, widget=None):
# Remove the widget and/or all the cascade empty splitters
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 splitter := widget.parentWidget():
while splitter.count() == 1 and splitter != self._baseWidget:
@ -271,18 +268,18 @@ class TTkKodeTab(TTkSplitter):
return item if type(item)==_TTkKodeTab else None
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()):
_wid = split.widget(i)
if issubclass(type(_wid), TTkSplitter):
if isinstance(_wid, TTkSplitter):
yield from _iterSplitter(_wid)
elif issubclass(type(_wid), _TTkKodeTab):
elif isinstance(_wid, _TTkKodeTab):
yield from _wid.iterItems()
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):
if issubclass(type(widget),_TTkKodeTab):
if isinstance(widget, _TTkKodeTab):
widget.setDropEventProxy(proxy)
return super().setDropEventProxy(proxy)

647
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
sys.path.append(os.path.join(sys.path[0],'../..'))
sys.path.append(os.path.join(sys.path[0],'../../libs/pyTermTk'))
import TermTk as ttk
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