From b06830390e9298830ef6fb99139045d945163658 Mon Sep 17 00:00:00 2001 From: Eugenio Parodi Date: Sun, 20 Oct 2024 23:42:32 +0100 Subject: [PATCH] Added Table examples --- tests/sandbox/Makefile | 4 +- tests/sandbox/sandbox.NerdFont.html | 3 + tests/t.ui/test.ui.032.table.01.py | 5 +- tests/t.ui/test.ui.032.table.02.py | 5 +- tests/t.ui/test.ui.032.table.03.py | 5 +- tests/t.ui/test.ui.032.table.04.py | 5 +- tests/t.ui/test.ui.032.table.05.py | 5 +- tests/t.ui/test.ui.032.table.06.py | 5 +- tests/t.ui/test.ui.032.table.07.py | 5 +- tests/t.ui/test.ui.032.table.08.py | 5 +- tests/t.ui/test.ui.032.table.09.py | 9 +- tutorial/000-examples.rst | 21 +- .../TTkTable/table.03.theming.color.01.py | 2 + .../TTkTable/table.03.theming.color.02.py | 12 +- .../TTkTable/table.03.theming.color.03.py | 16 ++ .../examples/TTkTable/table.04.methods.py | 227 ++++++++++++++++++ tutorial/examples/TTkTable/table.05.events.py | 129 ++++++++++ 17 files changed, 439 insertions(+), 24 deletions(-) create mode 100755 tutorial/examples/TTkTable/table.04.methods.py create mode 100755 tutorial/examples/TTkTable/table.05.events.py diff --git a/tests/sandbox/Makefile b/tests/sandbox/Makefile index 6642646b..af15558e 100644 --- a/tests/sandbox/Makefile +++ b/tests/sandbox/Makefile @@ -68,6 +68,7 @@ buildSandbox: www find ../../tmp/TermTk/ -name "*.py" | sed 's,.*tmp/,,' | sort | xargs tar cvzf bin/TermTk.tgz -C ../../tmp find ../../tutorial -name "*.py" | sort | xargs tar cvzf bin/tutorial.tgz find ../../demo/paint.py ../../demo/ttkode.py ../../demo/demo.py ../../demo/showcase/*.* | sort | xargs tar cvzf bin/demo.tgz + find ../../tests/ansi.images.json ../../tests/t.ui/*.* | sort | xargs tar cvzf bin/tests.tgz buildTestSandbox: www rm -rf bin @@ -77,4 +78,5 @@ buildTestSandbox: www find ../../TermTk/ -name "*.py" | sort | xargs tar cvzf bin/TermTk.tgz find ../../tutorial -name "*.py" | sort | xargs tar cvzf bin/tutorial.tgz - find ../../demo/paint.py ../../demo/ttkode.py ../../demo/demo.py ../../demo/showcase/*.* | sort | xargs tar cvzf bin/demo.tgz \ No newline at end of file + find ../../demo/paint.py ../../demo/ttkode.py ../../demo/demo.py ../../demo/showcase/*.* | sort | xargs tar cvzf bin/demo.tgz + find ../../tests/ansi.images.json ../../tests/t.ui/*.* | sort | xargs tar cvzf bin/tests.tgz diff --git a/tests/sandbox/sandbox.NerdFont.html b/tests/sandbox/sandbox.NerdFont.html index a87b89cf..438af693 100644 --- a/tests/sandbox/sandbox.NerdFont.html +++ b/tests/sandbox/sandbox.NerdFont.html @@ -119,6 +119,9 @@ await ttkProxy.loadLib("bin/tutorial.tgz"); term.write('Tutorials - Loaded\n\r') + await ttkProxy.loadLib("bin/tests.tgz"); + term.write('Tests - Loaded\n\r') + /* Sidebar Fetch all the files in the pyodide.FS And push them in the sidebar diff --git a/tests/t.ui/test.ui.032.table.01.py b/tests/t.ui/test.ui.032.table.01.py index a27570f8..76ffe142 100755 --- a/tests/t.ui/test.ui.032.table.01.py +++ b/tests/t.ui/test.ui.032.table.01.py @@ -119,11 +119,12 @@ data_list = [ ('XYLENES', 139.1, -47.8, 0.86)] parser = argparse.ArgumentParser() -parser.add_argument('-f', help='Full Screen', action='store_true') +parser.add_argument('-f', help='Full Screen (default)', action='store_true') +parser.add_argument('-w', help='Windowed', action='store_true') parser.add_argument('-t', help='Track Mouse', action='store_true') args = parser.parse_args() -fullScreen = args.f +fullScreen = not args.w mouseTrack = args.t root = ttk.TTk(title="pyTermTk Table Demo", mouseTrack=mouseTrack) diff --git a/tests/t.ui/test.ui.032.table.02.py b/tests/t.ui/test.ui.032.table.02.py index b562736b..001d9df6 100755 --- a/tests/t.ui/test.ui.032.table.02.py +++ b/tests/t.ui/test.ui.032.table.02.py @@ -190,11 +190,12 @@ class CustomColorModifier(ttk.TTkAlternateColor): return c[y%len(c)] parser = argparse.ArgumentParser() -parser.add_argument('-f', help='Full Screen', action='store_true') +parser.add_argument('-f', help='Full Screen (default)', action='store_true') +parser.add_argument('-w', help='Windowed', action='store_true') parser.add_argument('-t', help='Track Mouse', action='store_true') args = parser.parse_args() -fullScreen = args.f +fullScreen = not args.w mouseTrack = args.t root = ttk.TTk(title="pyTermTk Table Demo", mouseTrack=mouseTrack) diff --git a/tests/t.ui/test.ui.032.table.03.py b/tests/t.ui/test.ui.032.table.03.py index 45473dd4..b231951c 100755 --- a/tests/t.ui/test.ui.032.table.03.py +++ b/tests/t.ui/test.ui.032.table.03.py @@ -190,11 +190,12 @@ class CustomColorModifier(ttk.TTkAlternateColor): return c[y%len(c)] parser = argparse.ArgumentParser() -parser.add_argument('-f', help='Full Screen', action='store_true') +parser.add_argument('-f', help='Full Screen (default)', action='store_true') +parser.add_argument('-w', help='Windowed', action='store_true') parser.add_argument('-t', help='Track Mouse', action='store_true') args = parser.parse_args() -fullScreen = args.f +fullScreen = not args.w mouseTrack = args.t root = ttk.TTk(title="pyTermTk Table Demo", mouseTrack=mouseTrack) diff --git a/tests/t.ui/test.ui.032.table.04.py b/tests/t.ui/test.ui.032.table.04.py index de82d2c1..4cc212b8 100755 --- a/tests/t.ui/test.ui.032.table.04.py +++ b/tests/t.ui/test.ui.032.table.04.py @@ -195,11 +195,12 @@ class CustomColorModifier(ttk.TTkAlternateColor): return c[y%len(c)] parser = argparse.ArgumentParser() -parser.add_argument('-f', help='Full Screen', action='store_true') +parser.add_argument('-f', help='Full Screen (default)', action='store_true') +parser.add_argument('-w', help='Windowed', action='store_true') parser.add_argument('-t', help='Track Mouse', action='store_true') args = parser.parse_args() -fullScreen = args.f +fullScreen = not args.w mouseTrack = args.t root = ttk.TTk(title="pyTermTk Table Demo", mouseTrack=mouseTrack) diff --git a/tests/t.ui/test.ui.032.table.05.py b/tests/t.ui/test.ui.032.table.05.py index 3652dff9..d025a5d6 100755 --- a/tests/t.ui/test.ui.032.table.05.py +++ b/tests/t.ui/test.ui.032.table.05.py @@ -167,11 +167,12 @@ data_list3 = [ parser = argparse.ArgumentParser() -parser.add_argument('-f', help='Full Screen', action='store_true') +parser.add_argument('-f', help='Full Screen (default)', action='store_true') +parser.add_argument('-w', help='Windowed', action='store_true') parser.add_argument('-t', help='Track Mouse', action='store_true') args = parser.parse_args() -fullScreen = args.f +fullScreen = not args.w mouseTrack = args.t diff --git a/tests/t.ui/test.ui.032.table.06.py b/tests/t.ui/test.ui.032.table.06.py index e9a39d76..749b7f8e 100755 --- a/tests/t.ui/test.ui.032.table.06.py +++ b/tests/t.ui/test.ui.032.table.06.py @@ -38,13 +38,14 @@ sys.path.append(os.path.join(sys.path[0],'../..')) import TermTk as ttk parser = argparse.ArgumentParser() -parser.add_argument('-f', help='Full Screen', action='store_true') +parser.add_argument('-f', help='Full Screen (default)', action='store_true') +parser.add_argument('-w', help='Windowed', action='store_true') parser.add_argument('-t', help='Track Mouse', action='store_true') parser.add_argument('--csv', help='Open CSV File', type=argparse.FileType('r')) args = parser.parse_args() -fullScreen = args.f +fullScreen = not args.w mouseTrack = args.t # csvData = [] diff --git a/tests/t.ui/test.ui.032.table.07.py b/tests/t.ui/test.ui.032.table.07.py index 1acd08b0..ceb05653 100755 --- a/tests/t.ui/test.ui.032.table.07.py +++ b/tests/t.ui/test.ui.032.table.07.py @@ -38,13 +38,14 @@ sys.path.append(os.path.join(sys.path[0],'../..')) import TermTk as ttk parser = argparse.ArgumentParser() -parser.add_argument('-f', help='Full Screen', action='store_true') +parser.add_argument('-f', help='Full Screen (default)', action='store_true') +parser.add_argument('-w', help='Windowed', action='store_true') parser.add_argument('-t', help='Track Mouse', action='store_true') parser.add_argument('--csv', help='Open CSV File', type=argparse.FileType('r')) args = parser.parse_args() -fullScreen = args.f +fullScreen = not args.w mouseTrack = args.t # csvData = [] diff --git a/tests/t.ui/test.ui.032.table.08.py b/tests/t.ui/test.ui.032.table.08.py index d5248cde..f6f807d3 100755 --- a/tests/t.ui/test.ui.032.table.08.py +++ b/tests/t.ui/test.ui.032.table.08.py @@ -38,13 +38,14 @@ sys.path.append(os.path.join(sys.path[0],'../..')) import TermTk as ttk parser = argparse.ArgumentParser() -parser.add_argument('-f', help='Full Screen', action='store_true') +parser.add_argument('-f', help='Full Screen (default)', action='store_true') +parser.add_argument('-w', help='Windowed', action='store_true') parser.add_argument('-t', help='Track Mouse', action='store_true') parser.add_argument('--csv', help='Open CSV File', type=argparse.FileType('r')) args = parser.parse_args() -fullScreen = args.f +fullScreen = not args.w mouseTrack = args.t # csvData = [] diff --git a/tests/t.ui/test.ui.032.table.09.py b/tests/t.ui/test.ui.032.table.09.py index c91eaa4c..2c6adea9 100755 --- a/tests/t.ui/test.ui.032.table.09.py +++ b/tests/t.ui/test.ui.032.table.09.py @@ -38,14 +38,15 @@ sys.path.append(os.path.join(sys.path[0],'../..')) import TermTk as ttk parser = argparse.ArgumentParser() -parser.add_argument('-f', help='Full Screen', action='store_true') -parser.add_argument('-t', help='Track Mouse', action='store_true') +parser.add_argument('-f', help='Full Screen (default)', action='store_true') +parser.add_argument('-w', help='Windowed', action='store_true') +# parser.add_argument('-t', help='Track Mouse', action='store_true') parser.add_argument('--csv', help='Open CSV File', type=argparse.FileType('r')) args = parser.parse_args() -fullScreen = args.f -mouseTrack = args.t +fullScreen = not args.w +mouseTrack = True # csvData = [] # if args.csv: diff --git a/tutorial/000-examples.rst b/tutorial/000-examples.rst index a6afb5f1..6144aee7 100644 --- a/tutorial/000-examples.rst +++ b/tutorial/000-examples.rst @@ -69,9 +69,26 @@ TTkTable `TTkTable/table.02.custom.model.03.py `_ (`tryItOnline `_): -`TTkTable/table.03.theming.py `_ -(`tryItOnline `_): +`TTkTable/table.03.theming.color.01.py `_ +(`tryItOnline `_): +`TTkTable/table.03.theming.color.02.py `_ +(`tryItOnline `_): + +`TTkTable/table.03.theming.color.03.py `_ +(`tryItOnline `_): + +`TTkTable/table.03.theming.headers.01.py `_ +(`tryItOnline `_): + +`TTkTable/table.03.theming.lines.01.py `_ +(`tryItOnline `_): + +`TTkTable/table.04.methods.py `_ +(`tryItOnline `_): + +`TTkTable/table.05.events.py `_ +(`tryItOnline `_): TTkTextEdit =========== diff --git a/tutorial/examples/TTkTable/table.03.theming.color.01.py b/tutorial/examples/TTkTable/table.03.theming.color.01.py index db26db2a..fa6752fd 100755 --- a/tutorial/examples/TTkTable/table.03.theming.color.01.py +++ b/tutorial/examples/TTkTable/table.03.theming.color.01.py @@ -54,6 +54,8 @@ root = ttk.TTk(layout=ttk.TTkGridLayout(), mouseTrack=True) dataList = [[f"{(row,col)}" for col in range(10)] for row in range(101)] basicTableModel = ttk.TTkTableModelList(data=dataList) +# I am using as a style for the table a cell color with a +# TTkColor Dark Blue ("#000066") + a modifier which alternate the color with a standard BG_BLUE (="#0000FF") tableStyle = {'default': {'color': ttk.TTkColor.bg("#000066", modifier=ttk.TTkAlternateColor(alternateColor=ttk.TTkColor.BG_BLUE))} } # Table initialization: diff --git a/tutorial/examples/TTkTable/table.03.theming.color.02.py b/tutorial/examples/TTkTable/table.03.theming.color.02.py index ddc95b13..1cc73980 100755 --- a/tutorial/examples/TTkTable/table.03.theming.color.02.py +++ b/tutorial/examples/TTkTable/table.03.theming.color.02.py @@ -54,14 +54,24 @@ root = ttk.TTk(layout=ttk.TTkGridLayout(), mouseTrack=True) dataList = [[f"{(row,col)}" for col in range(10)] for row in range(101)] basicTableModel = ttk.TTkTableModelList(data=dataList) +# As First Style, I am using as +# Cell color: +# TTkColor Dark Green ("#006600") alternating with a darker green ("#003300") through the TTkAlternateColor modifier +# Selection Color: +# TTkColor Brighter green ("#00AA00") +# Hover Color: (the cell color under the mouse) +# TTkColor Cyan-ish ("#00AAAA") tableStyle1 = {'default': { 'color': ttk.TTkColor.bg("#006600", modifier=ttk.TTkAlternateColor(alternateColor=ttk.TTkColor.bg("#003300"))), 'selectedColor': ttk.TTkColor.bg("#00AA00"), 'hoverColor': ttk.TTkColor.bg("#00AAAA")} } + +# As Second Style, I am using this configuration, I guess it is self explainatory. +# I recommend to play with this and check the results. tableStyle2 = {'default': { 'color': ttk.TTkColor.bg("#660066", modifier=ttk.TTkAlternateColor(alternateColor=ttk.TTkColor.RST)), 'lineColor': ttk.TTkColor.fg("#FFFF00"), - 'headerColor': ttk.TTkColor.fg("#FFFF00")+ttk.TTkColor.bg("#660066"), + 'headerColor': ttk.TTkColor.fg("#FFFF00")+ttk.TTkColor.bg("#AA0000"), 'hoverColor': ttk.TTkColor.bg("#AAAAAA"), 'selectedColor': ttk.TTkColor.bg("#FFAA66"), 'separatorColor': ttk.TTkColor.fg("#330055")+ttk.TTkColor.bg("#660066")} } diff --git a/tutorial/examples/TTkTable/table.03.theming.color.03.py b/tutorial/examples/TTkTable/table.03.theming.color.03.py index 3142a20d..ea32c3f2 100755 --- a/tutorial/examples/TTkTable/table.03.theming.color.03.py +++ b/tutorial/examples/TTkTable/table.03.theming.color.03.py @@ -101,16 +101,32 @@ dataList = [[f"{(row,col)}" for col in range(10)] for row in range(101)] basicTableModel = ttk.TTkTableModelList(data=dataList) # Custom color styles + +# As First Style, I am defining an empty style only to show that +# the missing fields are taken from the class default style values tableStyle1 = {'default': {}} +# As Second Style, I am using as +# Cell color: +# TTkColor Dark Green ("#006600") alternating with a darker green ("#003300") through the TTkAlternateColor modifier +# Selection Color: +# TTkColor Brighter green ("#00AA00") +# Hover Color: (the cell color under the mouse) +# TTkColor Cyan-ish ("#00AAAA") tableStyle2 = {'default': { 'color': ttk.TTkColor.bg("#006600", modifier=ttk.TTkAlternateColor(alternateColor=ttk.TTkColor.bg("#003300"))), 'selectedColor': ttk.TTkColor.bg("#00AA00"), 'hoverColor': ttk.TTkColor.bg("#00AAAA")} } +# The third style is useful to check the results of +# alternating a color with the RST (Reset='\033[m0') property (the default cell color) tableStyle3 = {'default': { 'color': ttk.TTkColor.bg("#660066", modifier=ttk.TTkAlternateColor(alternateColor=ttk.TTkColor.RST))} } +# In the fourth and more flamboyant style +# I am using the CustomColorModifier (fefined few lines ago) +# which is supposed to return a different color for each line +# all the other fields I hope are self explainatory tableStyle4 = {'default': { 'color': ttk.TTkColor.bg("#000000", modifier=CustomColorModifier()), 'lineColor': ttk.TTkColor.fg("#FFFF00"), diff --git a/tutorial/examples/TTkTable/table.04.methods.py b/tutorial/examples/TTkTable/table.04.methods.py new file mode 100755 index 00000000..3d262860 --- /dev/null +++ b/tutorial/examples/TTkTable/table.04.methods.py @@ -0,0 +1,227 @@ +#!/usr/bin/env python3 + +# MIT License +# +# Copyright (c) 2024 Eugenio Parodi +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +# Those 2 lines are required to use the TermTk library in the main folder +import sys, os +sys.path.append(os.path.join(sys.path[0],'../../..')) + +import TermTk as ttk + +# This is a custom color modifier used to add a color pattern on each table line +class CustomColorModifier(ttk.TTkAlternateColor): + # I am defining a list of colors used as a circle list in this class + colors = ( + [ ttk.TTkColor.bg("#000066"), ttk.TTkColor.bg("#0000FF") ] * 3 + + [ ttk.TTkColor.bg("#003300"), ttk.TTkColor.bg("#006600") ] + + [ ttk.TTkColor.bg("#000066"), ttk.TTkColor.bg("#0000FF") ] * 3 + + [ttk.TTkColor.RST] * 5 + + [ #Rainbow-ish + ttk.TTkColor.fgbg("#00FFFF","#880000") + ttk.TTkColor.BOLD, + ttk.TTkColor.fgbg("#00FFFF","#FF0000") + ttk.TTkColor.BOLD, + ttk.TTkColor.fgbg("#0000FF","#FFFF00") + ttk.TTkColor.BOLD, + ttk.TTkColor.fgbg("#FF00FF","#00FF00") + ttk.TTkColor.BOLD, + ttk.TTkColor.fgbg("#FF0000","#00FFFF") + ttk.TTkColor.BOLD, + ttk.TTkColor.fgbg("#FFFF00","#0000FF") + ttk.TTkColor.BOLD, + ttk.TTkColor.fgbg("#00FF00","#FF00FF") + ttk.TTkColor.BOLD, + ttk.TTkColor.fgbg("#00FF00","#880088") + ttk.TTkColor.BOLD] + + [ttk.TTkColor.RST] * 3 + + [ttk.TTkColor.bg("#0000FF")] + + [ttk.TTkColor.RST] * 2 + + [ttk.TTkColor.bg("#0000FF")] + + [ttk.TTkColor.RST] + + [ttk.TTkColor.bg("#0000FF")] + + [ttk.TTkColor.RST] + + [ttk.TTkColor.bg("#0000FF")] * 2 + + [ttk.TTkColor.RST] * 3 + + [ttk.TTkColor.bg("#0000FF")] * 3 + + [ttk.TTkColor.RST] * 5 + + #Rainbow-ish 2 + [ttk.TTkColor.fgbg("#00FF00","#880088")] * 2 + + [ttk.TTkColor.fgbg("#00FF00","#FF00FF")] * 2 + + [ttk.TTkColor.fgbg("#FFFF00","#0000FF")] * 2 + + [ttk.TTkColor.fgbg("#FF0000","#00FFFF")] * 2 + + [ttk.TTkColor.fgbg("#FF00FF","#00FF00")] * 2 + + [ttk.TTkColor.fgbg("#0000FF","#FFFF00")] * 2 + + [ttk.TTkColor.fgbg("#00FFFF","#FF0000")] * 2 + + [ttk.TTkColor.fgbg("#00FFFF","#880000")] * 2 + + [ttk.TTkColor.RST] * 2 + ) + + # the exec function is called at each table line ('y') + def exec(self, x:int, y:int, base_color:ttk.TTkColor) -> ttk.TTkColor: + c = CustomColorModifier.colors + return c[y%len(c)] + +# root +# The root (TTk) widget is the main element of any pyTermTk apps +# It is responsible of any terminal routine, the terminal update +# and the events forwarded to any child widgets +# +# root initialization params used: +# +# layout = GridLayout +# I am using a grid layout in order to align/resize the table +# to the root widget (the terminal area) +# +# mouseTrack = True (optional) +# I am enabling the mouseTrack because the table can handle +# the mouse move events and highlight the cells under the cursor + +root = ttk.TTk(layout=ttk.TTkGridLayout(), mouseTrack=True) + +# The TTkTable is the widget responsible of handling and displaying a table model +# There are several table models available, in this example I am using +# TTkTableModelList which require a simple 2d List with the table data + +# I am initializing a simple list where any cell is a string representing its position (row,col) inside the list +dataList = [[f"{(row,col)}" for col in range(10)] for row in range(20)] +basicTableModel = ttk.TTkTableModelList(data=dataList) + +# Table initialization: +# parent = root +# In this example the root terminal (TTk) has this table as the only child +# since it is using a gridlayout, the child will be resized to occupy the entire +# area available +# +# tableModel = basicTableModel +# I guess this is self explainatory +# +table = ttk.TTkTable(tableModel=basicTableModel) + + +# Custom color styles + +# As Second Style, I am using as +# Cell color: +# TTkColor Dark Green ("#006600") alternating with a darker green ("#003300") through the TTkAlternateColor modifier +# Selection Color: +# TTkColor Brighter green ("#00AA00") +# Hover Color: (the cell color under the mouse) +# TTkColor Cyan-ish ("#00AAAA") +tableStyle2 = {'default': { + 'color': ttk.TTkColor.bg("#006600", modifier=ttk.TTkAlternateColor(alternateColor=ttk.TTkColor.bg("#003300"))), + 'selectedColor': ttk.TTkColor.bg("#00AA00"), + 'hoverColor': ttk.TTkColor.bg("#00AAAA")} } + +# The third style is useful to check the results of +# alternating a color with the RST (Reset='\033[m0') property (the default cell color) +tableStyle3 = {'default': { + 'color': ttk.TTkColor.bg("#660066", modifier=ttk.TTkAlternateColor(alternateColor=ttk.TTkColor.RST))} } + +# In the fourth and more flamboyant style +# I am using the CustomColorModifier (fefined few lines ago) +# which is supposed to return a different color for each line +# all the other fields I hope are self explainatory +tableStyle4 = {'default': { + 'color': ttk.TTkColor.bg("#000000", modifier=CustomColorModifier()), + 'lineColor': ttk.TTkColor.fg("#FFFF00"), + 'headerColor': ttk.TTkColor.fg("#FFFF00")+ttk.TTkColor.bg("#880000"), + 'hoverColor': ttk.TTkColor.bg("#AAAAAA"), + 'selectedColor': ttk.TTkColor.bg("#FFAA66"), + 'separatorColor': ttk.TTkColor.fg("#330055")+ttk.TTkColor.bg("#660066")} } + +# Themes Control +t1 = ttk.TTkRadioButton(text=' Theme 1', radiogroup='Themes', checked=True, maxWidth=15) +t2 = ttk.TTkRadioButton(text=' Theme 2', radiogroup='Themes') +t3 = ttk.TTkRadioButton(text=' Theme 3', radiogroup='Themes') +t4 = ttk.TTkRadioButton(text=' Theme 4', radiogroup='Themes') + +t1.clicked.connect(lambda : table.setStyle( None)) +t2.clicked.connect(lambda : table.mergeStyle(tableStyle2)) +t3.clicked.connect(lambda : table.mergeStyle(tableStyle3)) +t4.clicked.connect(lambda : table.mergeStyle(tableStyle4)) + +# Headers Visibility Checkboxes +ht = ttk.TTkCheckbox(text=' Header Top ',checked=True, maxWidth=20) +hl = ttk.TTkCheckbox(text=' Header Left',checked=True) + +ht.toggled.connect(table.horizontalHeader().setVisible) +hl.toggled.connect(table.verticalHeader().setVisible) + +# Lines/Separator Checkboxes +vli = ttk.TTkCheckbox(text=' V-Line',checked=True) +hli = ttk.TTkCheckbox(text=' H-Line',checked=True) + +vli.toggled.connect(table.setVSeparatorVisibility) +hli.toggled.connect(table.setHSeparatorVisibility) + +# Select Button +bs = ttk.TTkButton(text="Select", border=True)\ + +# This is a routine attached to the button click event +# which is selecting/deselecting a number of cells in the table +@ttk.pyTTkSlot() +def _customSelection(): + table.setSelection((0,0),(6,9),ttk.TTkK.TTkItemSelectionModel.Select) + table.setSelection((1,1),(4,7),ttk.TTkK.TTkItemSelectionModel.Clear) + table.setSelection((3,0),(1,2),ttk.TTkK.TTkItemSelectionModel.Select) + table.setSelection((1,3),(2,4),ttk.TTkK.TTkItemSelectionModel.Select) + table.setSelection((2,5),(2,4),ttk.TTkK.TTkItemSelectionModel.Select) + table.setSelection((0,9),(2,3),ttk.TTkK.TTkItemSelectionModel.Select) + +bs.clicked.connect(_customSelection) + +# I am placing the widget in the GridLayout +# Following this pattern +# Normally any component is evenly placed in the grid +# But Radio buttons and Checkboxes have fixed maximum height=1 +# this will force them to be placed at the bottom of the grid +# I manually force the first checkbox (=t1) maximum width to 15 +# so that the first column will be forced to be maximum 15 char width +# to keep the widget closer to the one in the second column +# +# Col 0 Col 1 Col 2 Col 3 +# ┌──────────────────────────────────────────────┐ +# row 0 │ TABLE │ +# │ rowspan = 1 │ +# │ colspan = 4 │ +# ├─────────┬───────────┬───────────────┬────────┤ +# row 1 │ Theme 1 │ Head Top │ BUTTON │ │ +# ├─────────┼───────────┤ rowspan = 3 ├────────┤ +# row 2 │ Theme 2 │ Head Left │ colspan = 1 │ │ +# ├─────────┼───────────┤ ├────────┤ +# row 3 │ Theme 3 │ V-Line │ │ │ +# ├─────────┼───────────┼───────────────┼────────┤ +# row 4 │ Theme 4 │ H-Line │ │ │ +# └─────────┴───────────┴───────────────┴────────┘ + +root.layout().addWidget(table,0,0,1,4) +root.layout().addWidget(bs, 1,2,3,1) + +root.layout().addWidget(t1, 1,0) +root.layout().addWidget(t2, 2,0) +root.layout().addWidget(t3, 3,0) +root.layout().addWidget(t4, 4,0) + +root.layout().addWidget(ht, 1,1) +root.layout().addWidget(hl, 2,1) +root.layout().addWidget(vli, 3,1) +root.layout().addWidget(hli, 4,1) + +# Adding a little touch, resizing the cols to its content +table.resizeColumnsToContents() + +# Start the main thread +root.mainloop() diff --git a/tutorial/examples/TTkTable/table.05.events.py b/tutorial/examples/TTkTable/table.05.events.py new file mode 100755 index 00000000..1735b616 --- /dev/null +++ b/tutorial/examples/TTkTable/table.05.events.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python3 + +# MIT License +# +# Copyright (c) 2024 Eugenio Parodi +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +# Those 2 lines are required to use the TermTk library in the main folder +import sys, os +sys.path.append(os.path.join(sys.path[0],'../../..')) + +import TermTk as ttk + +# root +# The root (TTk) widget is the main element of any pyTermTk apps +# It is responsible of any terminal routine, the terminal update +# and the events forwarded to any child widgets +# +# root initialization params used: +# +# layout = GridLayout +# I am using a grid layout in order to align/resize the table +# to the root widget (the terminal area) +# +# mouseTrack = True (optional) +# I am enabling the mouseTrack because the table can handle +# the mouse move events and highlight the cells under the cursor + +root = ttk.TTk(layout=ttk.TTkGridLayout(), mouseTrack=True) + +# The TTkTable is the widget responsible of handling and displaying a table model +# There are several table models available, in this example I am using +# TTkTableModelList which require a simple 2d List with the table data + +# I am initializing a simple list where any cell is a string representing its position (row,col) inside the list +dataList = [[f"{(row,col)}" for col in range(10)] for row in range(20)] +# I am adding also an int, float, multiline string, multiline Coloured TTkString +dataList[3][5] = 1234 +dataList[4][5] = 1234.1234 +dataList[5][5] = "Line1\nLine2" +dataList[6][5] = ttk.TTkString("Line1\nLine2\nLine3\nLine Four!!!",ttk.TTkColor.YELLOW) + +basicTableModel = ttk.TTkTableModelList(data=dataList) + +# Table initialization: +# parent = root +# In this example the root terminal (TTk) has this table as the only child +# since it is using a gridlayout, the child will be resized to occupy the entire +# area available +# +# tableModel = basicTableModel +# I guess this is self explainatory +# +table = ttk.TTkTable(tableModel=basicTableModel) + +# I am using 5 label widgets to display the results of the +# Table events +l_ch = ttk.TTkLabel(text="Cell Changed: xxxx", maxWidth=30) +l_cl = ttk.TTkLabel(text="Cell Clicked: xxxx") +l_dc = ttk.TTkLabel(text="DoubleClked : xxxx") +l_ce = ttk.TTkLabel(text="Cell Entered: xxxx") +l_cc = ttk.TTkLabel(text="Changed: xxxx") + +# I am placing also a text editor to report the content of the cell selected +t_ed = ttk.TTkTextEdit(lineNumber=True, maxHeight=6) + +# Yes, you can use lambda functions to process an event +# I don't recommend this and it is used in tbhis example only for testing purposes +table.cellChanged.connect( lambda r,c: l_ch.setText(f"Cell Changed: {r,c}")) +table.cellClicked.connect( lambda r,c: l_cl.setText(f"Cell Clicked: {r,c}")) +table.cellEntered.connect( lambda r,c: l_ce.setText(f"Cell Entered: {r,c}")) +table.cellDoubleClicked.connect( lambda r,c: l_dc.setText(f"DoubleClked : {r,c}")) +table.currentCellChanged.connect(lambda cr,cc,pr,pc: l_cc.setText(f"Changed:{cr,cc}<-{pr,pc}")) + +# In this Lambda function I am setting the text of the text editor to the content of the cell highlighted +table.cellEntered.connect( lambda r,c: t_ed.setText(table.model().ttkStringData(r,c))) + +# Col 0 Col 1 +# ┌──────────────────────────┐ +# row 0 │ TABLE │ +# │ rowspan = 1 │ +# │ colspan = 2 │ +# ├──────────┬───────────────┤ +# row 1 │ Label 1 │ Text Edit │ +# ├──────────┤ rowspan = 6 │ +# row 2 │ Label 2 │ colspan = 1 │ +# ├──────────┤ │ +# row 3 │ Label 3 │ │ +# ├──────────┤ │ +# row 4 │ Label 4 │ │ +# ├──────────┤ │ +# row 5 │ Label 5 │ │ +# ├──────────┤ │ +# row 6 │ Label 6 │ │ +# └──────────┴───────────────┘ + +root.layout().addWidget(table,0,0,1,2) + +root.layout().addWidget(l_ch, 1,0) +root.layout().addWidget(l_cl, 2,0) +root.layout().addWidget(l_dc, 3,0) +root.layout().addWidget(l_ce, 4,0) +root.layout().addWidget(l_cc, 5,0) +root.layout().addWidget(t_ed, 1,1,6,1) + +# Adding a little touch, resizing the cols and the rows to its content +table.resizeColumnsToContents() +table.resizeRowsToContents() + +# Start the main thread +root.mainloop()