18 changed files with 1141 additions and 126 deletions
@ -1,17 +0,0 @@
|
||||
{ |
||||
"compressed":{ |
||||
"Note1:" : "HEX Codes thanks to: https://github.com/ceccopierangiolieugenio/pyTermTk/tree/main/tools/dumbPaintTool", |
||||
"pepper" : "eJx9Vk1yFjsMfAtW4QhsOMEr/49dughVnCF3CFUsWGTBAsJ7QOBunIRuyZ6xHUgg7u/zKJLVkltz9+Lzh5f/6M+bd/jw6q27fY0foMQqQZKX7KXd/np4PPeOKs1L9Nj8fm0GqdE2/6eXm+7qNAhFvMcKg/eX+yK5SYyS+C0mCTBco5Um9ZAczIR/gAcZJnenifdJPP64dqPipTjJaTGqTbyLPKc5apIznsDmv9kGmwinJiHzZP5YTuxDkiMTlu2MJWFdNh3/YefhZttSbi4SsDissPx5xTmQU6iKaSRZEmGzw288FLsd8qBdgN23xY4UDLOGJB1WGH29jFBCH52iOcN2LYQlaIhZgneKRhWJQlMA18o0nCRFRXNYcFRXib1ThiGZLopmGJrQduuGED1OlxTNDt3oXSIukZv2bltJGAW5e74g7KUcFSwGvory/jgdOAvP3DoDiBeDxZvSP5w2y+F60+FzxQqj+8koamGPM3N8YPFJ5ccrc7Lms6LZoZwHa9WWmMGDtdgUrTbO874CNjswGbxiGhmRzLZdLlSlFAW7XJWXtNQ1BzQdYhIsJgQBS7fpYvCkDBeboK5ySfPjj5N7VLwpqMWBFJE8W+jLZYTbHQ4FNYKwgK5Mdn5cRlAz9IWCkR30kutZp4CV+qHQ21bbCbByAzKgSArWKIkPAFuFHQXsbAP0DcSixfX46GieZDR2pshg3TxJV6SHSWSn7HTZuAOzTsHqh7RQ0bQaoX2LgSWSD6NpozhqBh1IuVNdd27VpFasRGV0aqLeAlZvtQriEDp7qEUhrDnjxLgbhF4yHQeANSiCZGexnvEGZUPTD32jZktIS58+aVONMXXmRDhGBb2dNw3VCVvrcqYcCmk0IFsk+81MJcSPEeYxwyobbgzUIQLoClcUu52zDnSbWEQrzrgMHkZJYWEjOHbGoXiJRehiMdXARrAfmdIdh87mrlJmuPbhocvz5D7+nVyct3ExZ3i6UVai3cmRIl8vqJGbWWuC/4Quc07vQFsVKAS2e1Q8mc3hKbPUIeYZJn8ckervfmluzrOzuSGtnCnbmOI8TB2suVUHAYu3whcBGTKDL1IXWl8/FdcpRrJl4XGaZBgowaayCQ/nPdaNbMf3BYVTN13XzXmogJ3UFNMoEpWsbMMs0bYqWt95OivE5Y3MQ8UZNw9/uLF8BQjry51qf760Hy+NFLm2TH/y7M6GSiAibSTOUno27xWFF43XbdkcpdnfPqjwGzlVkGD9U2363u3Np39/A7RA/Jk=" , |
||||
"python" : "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" , |
||||
|
||||
"Note2:" : "Icons from: https://valletyh.itch.io/icon-pack", |
||||
"fire" : "eJytlUsOgyAQhrvoovEKbjhBg/iohoO0iUlv4B1c9AhtD9iTFMHwGAbBh9HEDP8Mw8cMjOfP83KSz+MufvKeDnlftpzxomOc8rIZft+XMPPKMRICZGqc1TWvK/EKrxHzIimO+p0iYMkMGUzyuAxTvAKKglFOLYW2WZJW/DVQI43Hx2E180WMdu5kKZGWiM37sZmjtq0CoJaRDMDUExwkNhtpsiXygwShKiUVbEm3NrSlKyEnIoRbj9dHmIFPUA0Rl6H6Vs5iMfSZkH3Nsr56Z4Nxti1zro5J1xICZ7HCsNrZ26IYB+sEDTSeq8AORpxUPFYw56kBYmvH6hhANHwiuoRYGEaYE4o6YTtMv8dY47Cx63DpDlvYFP9IdGffWCBoekP2vv4BVO4f6w==" , |
||||
"fireMini" : "eJylk01OAzEMhVl0xRW4A4rtJJPIF0HiDL1DFyxZsIBShLgPO+7ASXjOJPPTCXRBq1Zp/Y3t9xwfdi9fu6vyuvvE4ebe7fFRScpKQ1IcRb39ijjT/vv4OsXZeXxLHuPZGzCAeJgJIiWnnisSS9Y14oIlGUYiBUvi1wQ6GEQ5VEQMCWskBNSRqddcmLRlKKpvjImjvGL6io/myvWf0BwspSWOQWdvZHhaiIlFbAUoGyJhzVinaI+rKczwD1Zv9XDwcIsqFgSPBRW3nlLhEGqDGtNHzZ10iDSfyx/4IUO1YNEcSrKfMWjmCOrtgg2PZ0Ze8spKJZRytZQpwDlvqCZpbhxXjn2XMy9mLpAZA/BwBqK9QAuQ0ujEaTHKhAsFLrUxkY2WzIn3RTZSDJkb5PCQ11Ly9H+7frmUoWb4WGxitpFJtTJlu7a00U220m2hyy5Khxmm6XcZ6wJ12r6WPXNniC9C2ipypxtXNqOuQKYt0Zd8KqY93/4AlgU7wQ==", |
||||
"key" : "eJzFVLsRwjAMpYCGFWgyAedPPua0CHfM4B1SMAKwHF0mQYkTHDuW45gCXwpLeZKefm73z+6wG871jZfTjenCHLyCVCBAVBXwukZBd697QA3lJAvBQDGEtfi5yEsKklcKOEOEGEPpo2UUjWz869GZH8Y39sh8s7PGXHBQDchGz0x5jfoGFhAqqvVm8yqmrBZ/qEzJymVk6hon9DHHm1GPsKlmbnW31CNpEDOY9bIsIYDqtQT9EMgZBAe3MjBB0HwFiM1oZ5sRKMOGNU2vjqelt4Lg7+Vu6NOL/7fWJrUs0v/ojOv4+7Li9rdxeZw/gO97Ug==", |
||||
"sword" : "eJzFU8kNwjAQ5AEfWuCTCpDXcXxoG0GihvTAgxKAAvnRBevElo/YJogHUVaKNpPZmfHmsr2/dpvpOj3p4XBmIxUKjRxhkAiKIWgYO9vts+4M48Pga3w+LgHIFAJQCcfHe6AioFA1IPWvVsPeC5kBxACCxsp0QkToFNeAQWJbyoKxZc70JNsRgjYIxiBnsoJLrHXdH8xFGj8fyE/mVthbiEm3oJVDTc1iMdfai/a8ac/PISiIKG9lX4DKNwTQkB2jyqiQVZxWJYSFtwzY/u9qO5wbCZLTE/DKAx1I4s5TjT6+Vg1+npml1fh2ZfBlvZwiknRzp0MOKA3KbKd812+UXT1mI05hXCNNKzPFOaRnXUzbcZVlfOUg63aTltvxDd6kgOU=", |
||||
"ring" : "eJylVcFtwzAM7KOPIiv0owkKU7JqCXxkjQCdwTvkkRHaDphJoji2LJGUrMQBHATkmeSdTsz5/e/48TZ9Ti78+PzpRqXCNxqHGjsEY1BDN17/L0k0RBC8y6LgBgTwaAF7ijpXUGuHMkobGyoBQjfUcdog2PD4Auw+8WPo8TBx5VRr08fo3M7a5clgSVxg+ULBpuG07YNQHp0WRcuga2ppvLy78xzGVN17vid5VeIuO0GQUj6YTCCi40sFG4bLaCfh3mCoDkB7D4DfAzo/i5LC1vmihR+o5Z3qudBSLfJzD8iXh0krOoUZuQnV1JGpHDaUSpbUhqq5iqokyiQZy8QdsUtHKslaMb1QSZ/IQXG6MSn7Yz9dteVvxrjg5Po+enqJ57xLd49uIn4lL2KiWc2mYeZ/F7UtZkG7RonJspDNL9qW3JpnhhPY/n7dAHoxGOQ=", |
||||
"diamond" : "eJyVlU1uhDAMhbuoVKlX6MbddVXFhDAgX6RSz8AdWPQIbQ/YkzQwgbwkjgIjZpgxH/55Np7l8eft6WF7fbz6Ly+fZiYifxI7SifWCU9GOufmv98vxSz9+pvdJF0/BG45OGeF+SadHe7cekN4rxyi/oON92JvKnpwRoZeeHRXKGafr2OF6tlfHENt8/NWvpJSUnxeVK14sFfTKIqgaDXWx5juVmgJeClBdIvhottdGahzlyEDmkodPkEoul5+kadeZk1mUC9kgzMLXJSpNoxJ9wqZ1dnNNCUUOkhGu2CZvSHf2foLneN8JjKDOSYJWpFKQkIDb0m14gDXClSg2rMLjK75JcVrj3d9Z53F9KkrulPhGkslH868F6VXVfWzN+scLAF1Myxxh1JT5rTLKYTHmcWVx25Hz/9tcOlpWR4Rvt//AVu00Dg=", |
||||
"peach" : "eJytVEtuhTAM7KKL6l2hm6i7bioCIR/5Ik96Z+AOLHqEtgfsSRogIYmxXfpUhAQME8ceTzw/fr4+PazX9SW+PN+6SSkVHzB46KEfR9BmAD3q6fvrvcW1BeMXuP6jgwcLFsNLDD9C10bpYnADXQyTYvbxU7shsmaGpXsLvTYQgkCqdpt5lvMQHLgxBZouv/FWdc5ps+GlMO0CeJTyDpP149R3xeWgrA5NpLQPJymGS9EFFHbIICnzRqG0n+6UNvuwpF6Joxow65s8TpIp0xkXXw92ykUcSEWuDUuE/WhUIqdFCi9JdRdhDBZGid6wy330mywe68vSDNKXZ1uywX9NPOmWKEPsYIh3m3NGBaUTpkjtKQNWiWEPo2zxxORKouVbf/9XdZWv91hSyXzm5LnF+TbNFnJmLMkWxnburCNaCnsg2FokyY5jQpptjC+olfe04AyHGk14L2F8lYZMl4+3HxigIEs=", |
||||
"whip" : "eJylU8ERwiAQ9KGftOCHChyPhEDmnv6swBlroAcelqAWaCViQHIQCBNlyCRzt7e3CxezfZx3m3FdTvZjfz1qxph9YauQIwdAUC2CEPr1vMVxYeOdnMcD3hTwhqZADQjQ2Qd0IY7dGOglysHuEqyiUDfOXU6s65Co9IfBSpyelgCqEtc5GRXPk2nTn+nz1jxJ/VrieNp0xsLS4aoKz/tPsTPavy6BRG+ls4tStCAMzXQAIV0WSG2mrvyaALxDwe0m7dxcB0g/oBIoVORgEFZ8iyr+Sb5Qr/XjsAeUMjqSUJpDLQCJDpPVb0K9s1CQRaUToiBjqZuQdrIdeAUq3zFbm0J1cz+8AbE/aBQ=" |
||||
} |
||||
} |
||||
@ -0,0 +1,84 @@
|
||||
#!/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. |
||||
|
||||
# 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 example show the basic Drag and Drop functionality; |
||||
# |
||||
# Each TTkWidget include 4 methods to handle the Drag and Drop events: |
||||
# - dragEnterEvent |
||||
# - dragLeaveEvent |
||||
# - dragMoveEvent |
||||
# - dropEvent |
||||
# Overriding any of those methods in a subclass will allow the widget to handle the DnD events |
||||
# |
||||
# To start a Drag and Drop operation, the TTkDrag object must be created and executed. |
||||
# The Drag and Drop operation is usually started after a mouseDragEvent as shown in |
||||
# this example, but it can be started after any other events/methods or signals. |
||||
|
||||
class DragDrop(ttk.TTkFrame): |
||||
def mouseDragEvent(self, evt:ttk. TTkMouseEvent) -> bool: |
||||
if evt.key == ttk. TTkMouseEvent.LeftButton: |
||||
# Create a new drag object and set some text as DnD Data |
||||
drag = ttk.TTkDrag() |
||||
drag.setData(f"Test DnD ({self.title()})") |
||||
ttk.TTkLog.debug(f"Drag ({self.title()}) -> {drag.data()}, pos={evt.x},{evt.y}") |
||||
# Start the drag operation |
||||
drag.exec() |
||||
return True |
||||
|
||||
def dropEvent(self, evt:ttk.TTkDnDEvent) -> bool: |
||||
ttk.TTkLog.debug(f"Drop ({self.title()}) <- {evt.data()}, pos={evt.x},{evt.y}") |
||||
return True |
||||
|
||||
# Create the root application |
||||
# and set its layout to TTkGridLayout in order to |
||||
# place the widgets in the following way: |
||||
# |
||||
# Col 0 Col 1 |
||||
# +----------------+----------------+ |
||||
# Row 0 | DragDrop 1 | DragDrop 2 | |
||||
# + +----------------+ |
||||
# Row 1 | | DragDrop 3 | |
||||
# +----------------+----------------+ |
||||
# Row 2 | Log Viewer | |
||||
# +----------------+----------------+ |
||||
# |
||||
root = ttk.TTk() |
||||
root.setLayout(ttk.TTkGridLayout()) |
||||
|
||||
# Add the DragDrop widgets to the root layout |
||||
root.layout().addWidget(DragDrop(title="DnD 1"),0,0,2,1) |
||||
root.layout().addWidget(DragDrop(title="DnD 2"),0,1,1,1) |
||||
root.layout().addWidget(DragDrop(title="DnD 3"),1,1,1,1) |
||||
|
||||
# Add a LogViewer at the bottom to display the log messages |
||||
# (Row 2, Col 0, RowSpan 1, ColSpan 2) |
||||
root.layout().addWidget(ttk.TTkLogViewer(follow=True),2,0,1,2) |
||||
|
||||
root.mainloop() |
||||
@ -0,0 +1,96 @@
|
||||
#!/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. |
||||
|
||||
# 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 example show the basic Drag and Drop functionality; |
||||
# |
||||
# Each TTkWidget include 4 methods to handle the Drag and Drop events: |
||||
# - dragEnterEvent |
||||
# - dragLeaveEvent |
||||
# - dragMoveEvent |
||||
# - dropEvent |
||||
# Overriding any of those methods in a subclass will allow the widget to handle the DnD events |
||||
# |
||||
# To start a Drag and Drop operation, the TTkDrag object must be created and executed. |
||||
# The Drag and Drop operation is usually started after a mouseDragEvent as shown in |
||||
# this example, but it can be started after any other events/methods or signals. |
||||
|
||||
class DragDrop(ttk.TTkFrame): |
||||
def mouseDragEvent(self, evt:ttk. TTkMouseEvent) -> bool: |
||||
if evt.key == ttk. TTkMouseEvent.LeftButton: |
||||
# Create a new drag object and set some text as DnD Data |
||||
drag = ttk.TTkDrag() |
||||
drag.setData(f"Test DnD ({self.title()})") |
||||
ttk.TTkLog.debug(f"Drag ({self.title()}) -> {drag.data()}, pos={evt.pos()}") |
||||
# Start the drag operation |
||||
drag.exec() |
||||
return True |
||||
|
||||
def dragEnterEvent(self, evt:ttk.TTkDnDEvent) -> bool: |
||||
ttk.TTkLog.debug(f"Drag Enter ({self.title()}) - {evt.data()}, pos={evt.pos()}") |
||||
return True |
||||
|
||||
def dragLeaveEvent(self, evt:ttk.TTkDnDEvent) -> bool: |
||||
ttk.TTkLog.debug(f"Drag Leave ({self.title()}) - {evt.data()}, pos={evt.pos()}") |
||||
return True |
||||
|
||||
def dragMoveEvent(self, evt:ttk.TTkDnDEvent) -> bool: |
||||
ttk.TTkLog.debug(f"Drag Move ({self.title()}) - {evt.data()}, pos={evt.pos()}") |
||||
return True |
||||
|
||||
def dropEvent(self, evt:ttk.TTkDnDEvent) -> bool: |
||||
ttk.TTkLog.debug(f"Drop ({self.title()}) <- {evt.data()}, pos={evt.pos()}") |
||||
return True |
||||
|
||||
# Create the root application |
||||
# and set its layout to TTkGridLayout in order to |
||||
# place the widgets in the following way: |
||||
# |
||||
# Col 0 Col 1 |
||||
# +----------------+----------------+ |
||||
# Row 0 | DragDrop 1 | DragDrop 2 | |
||||
# + +----------------+ |
||||
# Row 1 | | DragDrop 3 | |
||||
# +----------------+----------------+ |
||||
# Row 2 | Log Viewer | |
||||
# +----------------+----------------+ |
||||
# |
||||
root = ttk.TTk() |
||||
root.setLayout(ttk.TTkGridLayout()) |
||||
|
||||
# Add the DragDrop widgets to the root layout |
||||
root.layout().addWidget(DragDrop(title="DnD 1"),0,0,2,1) |
||||
root.layout().addWidget(DragDrop(title="DnD 2"),0,1,1,1) |
||||
root.layout().addWidget(DragDrop(title="DnD 3"),1,1,1,1) |
||||
|
||||
# Add a LogViewer at the bottom to display the log messages |
||||
# (Row 2, Col 0, RowSpan 1, ColSpan 2) |
||||
root.layout().addWidget(ttk.TTkLogViewer(follow=True),2,0,1,2) |
||||
|
||||
root.mainloop() |
||||
@ -0,0 +1,135 @@
|
||||
#!/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. |
||||
|
||||
# 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 example show the basic Drag and Drop functionality; |
||||
# |
||||
# Each TTkWidget include 4 methods to handle the Drag and Drop events: |
||||
# - dragEnterEvent |
||||
# - dragLeaveEvent |
||||
# - dragMoveEvent |
||||
# - dropEvent |
||||
# Overriding any of those methods in a subclass will allow the widget to handle the DnD events |
||||
# |
||||
# To start a Drag and Drop operation, the TTkDrag object must be created and executed. |
||||
# The Drag and Drop operation is usually started after a mouseDragEvent as shown in |
||||
# this example, but it can be started after any other events/methods or signals. |
||||
# |
||||
# Here I am exploring the different interactions between the Drag and Drop events |
||||
# In particular I am testing the dragLeaveEvent whch is triggered only if the |
||||
# dragMoveEvent or dragEnterEvent has been handled (returned True) before. |
||||
|
||||
class DragDrop(ttk.TTkFrame): |
||||
# Basic Drag and Drop widget |
||||
def mouseDragEvent(self, evt:ttk. TTkMouseEvent) -> bool: |
||||
if evt.key == ttk. TTkMouseEvent.LeftButton: |
||||
# Create a new drag object and set some text as DnD Data |
||||
drag = ttk.TTkDrag() |
||||
drag.setData(f"Test DnD ({self.title()})") |
||||
ttk.TTkLog.debug(f"Drag ({self.title()}) -> {drag.data()}, pos={evt.pos()}") |
||||
# Start the drag operation |
||||
drag.exec() |
||||
return True |
||||
|
||||
def dropEvent(self, evt:ttk.TTkDnDEvent) -> bool: |
||||
ttk.TTkLog.debug(f"Drop ({self.title()}) <- {evt.data()}, pos={evt.pos()}") |
||||
return True |
||||
|
||||
|
||||
class DragDropMove(DragDrop): |
||||
# Drag and Drop widget that handles only the dragMoveEvent |
||||
def dragMoveEvent(self, evt:ttk.TTkDnDEvent) -> bool: |
||||
ttk.TTkLog.debug(f"Drag Move ({self.title()}) - {evt.data()}, pos={evt.pos()}") |
||||
return True |
||||
|
||||
|
||||
class DragDropEnter(DragDrop): |
||||
# Drag and Drop widget that handles only the dragEnterEvent |
||||
def dragEnterEvent(self, evt:ttk.TTkDnDEvent) -> bool: |
||||
ttk.TTkLog.debug(f"Drag Enter ({self.title()}) - {evt.data()}, pos={evt.pos()}") |
||||
return True |
||||
|
||||
|
||||
class DragDropLeave1(DragDrop): |
||||
# Drag and Drop widget that handles the dragEnterEvent and dragLeaveEvent |
||||
def dragEnterEvent(self, evt:ttk.TTkDnDEvent) -> bool: |
||||
ttk.TTkLog.debug(f"Drag Enter ({self.title()}) - {evt.data()}, pos={evt.pos()}") |
||||
return True |
||||
|
||||
def dragLeaveEvent(self, evt:ttk.TTkDnDEvent) -> bool: |
||||
ttk.TTkLog.debug(f"Drag Leave ({self.title()}) - {evt.data()}, pos={evt.pos()}") |
||||
return True |
||||
|
||||
class DragDropLeave2(DragDrop): |
||||
# Drag and Drop widget that handles the dragMoveEvent and dragLeaveEvent |
||||
def dragMoveEvent(self, evt:ttk.TTkDnDEvent) -> bool: |
||||
ttk.TTkLog.debug(f"Drag Move ({self.title()}) - {evt.data()}, pos={evt.pos()}") |
||||
return True |
||||
|
||||
def dragLeaveEvent(self, evt:ttk.TTkDnDEvent) -> bool: |
||||
ttk.TTkLog.debug(f"Drag Leave ({self.title()}) - {evt.data()}, pos={evt.pos()}") |
||||
return True |
||||
|
||||
class DragDropLeave3(DragDrop): |
||||
# Drag and Drop widget that handles only the dragLeaveEvent |
||||
# NOTE: |
||||
# This widget will never receive the dragLeaveEvent because |
||||
# neither the dragMoveEvent or dragEnterEvent are handled |
||||
def dragLeaveEvent(self, evt:ttk.TTkDnDEvent) -> bool: |
||||
ttk.TTkLog.debug(f"Drag Leave ({self.title()}) - {evt.data()}, pos={evt.pos()}") |
||||
return True |
||||
|
||||
# Create the root application |
||||
# and set its layout to TTkGridLayout in order to |
||||
# place the widgets in the following way: |
||||
# |
||||
# Col 0 Col 1 Col 2 |
||||
# +----------------+----------------+-----------------+ |
||||
# Row 0 | DnD Move | DnD Enter | |
||||
# +----------------+----------------+-----------------+ |
||||
# Row 1 | DnD Move,Leave | DnD only Leave | DnD Enter,Leave | |
||||
# +----------------+----------------+-----------------+ |
||||
# Row 2 | Log Viewer | |
||||
# +----------------+----------------+-----------------+ |
||||
# |
||||
root = ttk.TTk() |
||||
root.setLayout(ttk.TTkGridLayout()) |
||||
|
||||
# Add the DragDrop widgets to the root layout |
||||
root.layout().addWidget(DragDropMove( title="DnD Move"), 0,0) |
||||
root.layout().addWidget(DragDropEnter( title="DnD Enter"), 0,1,1,2) |
||||
root.layout().addWidget(DragDropLeave2(title="DnD Move,Leave"), 1,0) |
||||
root.layout().addWidget(DragDropLeave1(title="DnD Enter,Leave"), 1,2) |
||||
root.layout().addWidget(DragDropLeave3(title="DnD only Leave"), 1,1) |
||||
|
||||
# Add a LogViewer at the bottom to display the log messages |
||||
# (Row 2, Col 0, RowSpan 1, ColSpan 2) |
||||
root.layout().addWidget(ttk.TTkLogViewer(follow=True),2,0,1,3) |
||||
|
||||
root.mainloop() |
||||
@ -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. |
||||
|
||||
# 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 example show the basic Drag and Drop pixmap usage; |
||||
# |
||||
# Anytime a Drag and Drop operation is started, a new TTkButton is created |
||||
# and used as DnD Data and Pixmap. |
||||
# The same data object is added to the frame in the dropEvent and moved to the mouse coordinates. |
||||
|
||||
class DragDrop(ttk.TTkFrame): |
||||
def mouseDragEvent(self, evt:ttk. TTkMouseEvent) -> bool: |
||||
if evt.key == ttk. TTkMouseEvent.LeftButton: |
||||
# Create a new drag object and |
||||
# a new TTkButton as DnD Data and Pixmap |
||||
# the default TTkButton canvas will be used as Pixmap |
||||
button = ttk.TTkButton(text=f"Test DnD ({self.title()})", border=True, size=(20,3)) |
||||
drag = ttk.TTkDrag() |
||||
drag.setData(button) |
||||
drag.setPixmap(button) |
||||
ttk.TTkLog.debug(f"Drag ({self.title()}) -> {button.text()}, pos={evt.x},{evt.y}") |
||||
# Start the drag operation |
||||
drag.exec() |
||||
return True |
||||
|
||||
def dropEvent(self, evt:ttk.TTkDnDEvent) -> bool: |
||||
button:ttk.TTkButton = evt.data() |
||||
self.layout().addWidget(button) |
||||
# Since the frame by default has a padding of 1 |
||||
# I align the button to the mouse coordinates by subtracting the Top/Left padding size |
||||
t,b,l,r = self.getPadding() |
||||
button.move(evt.x-l, evt.y-t) |
||||
ttk.TTkLog.debug(f"Drop ({self.title()}) <- {button.text()}, pos={evt.x},{evt.y}") |
||||
return True |
||||
|
||||
# Create the root application |
||||
# and set its layout to TTkGridLayout in order to |
||||
# place the widgets in the following way: |
||||
# |
||||
# Col 0 Col 1 |
||||
# +----------------+----------------+ |
||||
# Row 0 | DragDrop 1 | DragDrop 2 | |
||||
# + +----------------+ |
||||
# Row 1 | | DragDrop 3 | |
||||
# +----------------+----------------+ |
||||
# Row 2 | Log Viewer | |
||||
# +----------------+----------------+ |
||||
# |
||||
root = ttk.TTk() |
||||
root.setLayout(ttk.TTkGridLayout()) |
||||
|
||||
# Add the DragDrop widgets to the root layout |
||||
root.layout().addWidget(DragDrop(title="DnD 1"),0,0,2,1) |
||||
root.layout().addWidget(DragDrop(title="DnD 2"),0,1,1,1) |
||||
root.layout().addWidget(DragDrop(title="DnD 3"),1,1,1,1) |
||||
|
||||
# Add a LogViewer at the bottom to display the log messages |
||||
# (Row 2, Col 0, RowSpan 1, ColSpan 2) |
||||
root.layout().addWidget(ttk.TTkLogViewer(follow=True),2,0,1,2) |
||||
|
||||
root.mainloop() |
||||
@ -0,0 +1,110 @@
|
||||
#!/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. |
||||
|
||||
# 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 example show more advance Drag and Drop pixmap usage; |
||||
# |
||||
# When the Drag and Drop operation is started, a TTkLabel widget is created |
||||
# but a new canvas is built to be used as pixmap. |
||||
# This approach increase the flexibility on the styling of the full drag and drop operation |
||||
|
||||
class DragDrop(ttk.TTkFrame): |
||||
def mouseDragEvent(self, evt:ttk. TTkMouseEvent) -> bool: |
||||
# Create a new drag object, a new TTkLabel as DnD Data and |
||||
# a custom Pixmap drawn as a titled box of fixed sizes around |
||||
# a snippet of the label's text |
||||
label = ttk.TTkLabel(text="Lorem ipsum dolor sit amet,\nconsectetur adipiscing elit,\nsed do eiusmod tempor incididunt ut\nlabore et dolore magna aliqua.", size=(10,1)) |
||||
|
||||
pixmap = ttk.TTkCanvas(width=17,height=5) |
||||
pixmap.drawText(pos=(0,0),text="╭───────────────╮") |
||||
pixmap.drawText(pos=(2,0),text=f"╼ {self.title()} ╾") # Here for simplicity I am writing the title over the top border |
||||
pixmap.drawText(pos=(0,1),text="│Lorem ipsum dol│") |
||||
pixmap.drawText(pos=(0,2),text="│consectetur adi│") |
||||
pixmap.drawText(pos=(0,3),text="│sed do eiusmod │") |
||||
pixmap.drawText(pos=(0,4),text="╰───────────────╯") |
||||
|
||||
# The next condition is meant to show that you can |
||||
# handle also the Drag and Drop with the Right or Middle mouse buttons. |
||||
if evt.key == ttk. TTkMouseEvent.LeftButton: |
||||
pixmap.drawText(pos=(0,4),text="╰───────╼ Left ╾╯") |
||||
elif evt.key == ttk. TTkMouseEvent.RightButton: |
||||
pixmap.drawText(pos=(0,4),text="╰──────╼ Right ╾╯") |
||||
elif evt.key == ttk. TTkMouseEvent.MidButton: |
||||
pixmap.drawText(pos=(0,4),text="╰────╼ Eugenio ╾╯") |
||||
|
||||
drag = ttk.TTkDrag() |
||||
drag.setData(label) |
||||
drag.setPixmap(pixmap) |
||||
ttk.TTkLog.debug(f"Drag ({self.title()}) -> pos={evt.x},{evt.y}") |
||||
# Start the drag operation |
||||
drag.exec() |
||||
return True |
||||
|
||||
def dropEvent(self, evt:ttk.TTkDnDEvent) -> bool: |
||||
# Similar to the previous example |
||||
# I am retrieving the TTkLabel widget used as Drag'nDrop data |
||||
# and I am placing it inside the current Frame |
||||
# This time I am not removing the padding sizes from the |
||||
# position due to the frame I draw in the pixmap that |
||||
# already changed the offset of the text being aligned to the final |
||||
# dropped Label position. |
||||
# BTW, I am not a genious that can figure out all of this upfront, |
||||
# this is just the result of trial and errors |
||||
label:ttk.TTkLabel = evt.data() |
||||
self.layout().addWidget(label) |
||||
label.move(evt.x, evt.y) |
||||
ttk.TTkLog.debug(f"Drop ({self.title()}) <- pos={evt.x},{evt.y}") |
||||
return True |
||||
|
||||
# Create the root application |
||||
# and set its layout to TTkGridLayout in order to |
||||
# place the widgets in the following way: |
||||
# |
||||
# Col 0 Col 1 |
||||
# +----------------+----------------+ |
||||
# Row 0 | DragDrop 1 | DragDrop 2 | |
||||
# + +----------------+ |
||||
# Row 1 | | DragDrop 3 | |
||||
# +----------------+----------------+ |
||||
# Row 2 | Log Viewer | |
||||
# +----------------+----------------+ |
||||
# |
||||
root = ttk.TTk() |
||||
root.setLayout(ttk.TTkGridLayout()) |
||||
|
||||
# Add the DragDrop widgets to the root layout |
||||
root.layout().addWidget(DragDrop(title="DnD 1"),0,0,2,1) |
||||
root.layout().addWidget(DragDrop(title="DnD 2"),0,1,1,1) |
||||
root.layout().addWidget(DragDrop(title="DnD 3"),1,1,1,1) |
||||
|
||||
# Add a LogViewer at the bottom to display the log messages |
||||
# (Row 2, Col 0, RowSpan 1, ColSpan 2) |
||||
root.layout().addWidget(ttk.TTkLogViewer(follow=True),2,0,1,2) |
||||
|
||||
root.mainloop() |
||||
@ -0,0 +1,134 @@
|
||||
#!/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 json |
||||
import random |
||||
|
||||
# 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 |
||||
|
||||
# Load the images from the ansi.images.json file |
||||
# Each entry is a compressed base64 encoded image as a multiline TTkString |
||||
imagesFile = os.path.join(os.path.dirname(os.path.abspath(__file__)),'../ansi.images.json') |
||||
with open(imagesFile) as f: |
||||
d = json.load(f) |
||||
# Image exported by the Dumb Paint Tool - Removing the extra '\n' at the end |
||||
diamond = ttk.TTkString(ttk.TTkUtil.base64_deflate_2_obj(d['compressed']['diamond' ])[0:-1]) |
||||
fire = ttk.TTkString(ttk.TTkUtil.base64_deflate_2_obj(d['compressed']['fire' ])[0:-1]) |
||||
key = ttk.TTkString(ttk.TTkUtil.base64_deflate_2_obj(d['compressed']['key' ])[0:-1]) |
||||
peach = ttk.TTkString(ttk.TTkUtil.base64_deflate_2_obj(d['compressed']['peach' ])[0:-1]) |
||||
pepper = ttk.TTkString(ttk.TTkUtil.base64_deflate_2_obj(d['compressed']['pepper' ])[0:-1]) |
||||
python = ttk.TTkString(ttk.TTkUtil.base64_deflate_2_obj(d['compressed']['python' ])[0:-1]) |
||||
ring = ttk.TTkString(ttk.TTkUtil.base64_deflate_2_obj(d['compressed']['ring' ])[0:-1]) |
||||
sword = ttk.TTkString(ttk.TTkUtil.base64_deflate_2_obj(d['compressed']['sword' ])[0:-1]) |
||||
whip = ttk.TTkString(ttk.TTkUtil.base64_deflate_2_obj(d['compressed']['whip' ])[0:-1]) |
||||
|
||||
# Calculate the size of the image, this is a simple helper function. |
||||
# Since the images are simple ANSI strings, |
||||
# the size is calculated by counting the lines and the max width of the lines |
||||
def imageSize(img:ttk.TTkString) -> int: |
||||
lines = img.split('\n') |
||||
return ( |
||||
max(line.termWidth() for line in lines), |
||||
len(lines)) |
||||
|
||||
# This example show a showcase of the Drag and Drop pixmap functionality; |
||||
# |
||||
# Anytime a Drag and Drop operation is started, a random image is selected and used as Pixmap. |
||||
# |
||||
# In order to display the images after the drop event, the pixmaps are stored in a list |
||||
# and the paintEvent routine is used to draw them on the canvas. |
||||
|
||||
class DragDrop(ttk.TTkFrame): |
||||
def __init__(self, **kwargs): |
||||
# The list of pixmaps to be drawn in the paintEvent routine |
||||
self.pixmaps = [] |
||||
super().__init__(**kwargs) |
||||
|
||||
def mouseDragEvent(self, evt:ttk. TTkMouseEvent) -> bool: |
||||
if evt.key == ttk. TTkMouseEvent.LeftButton: |
||||
# Create a new drag object and |
||||
# a random image is chosen |
||||
imageString = random.choice([diamond,fire,key,peach,ring,sword,whip,pepper,python]) |
||||
|
||||
# A canvas is created and the ANSI String is drawn on it line by line |
||||
w,h = imageSize(imageString) |
||||
pixmap = ttk.TTkCanvas(width=w, height=h+1) |
||||
pixmap.setTransparent(True) |
||||
pixmap.drawText(pos=(0,0), text=self.title()) |
||||
for y,line in enumerate(imageString.split('\n')): |
||||
pixmap.drawTTkString(pos=(0,y+1), text=line) |
||||
|
||||
drag = ttk.TTkDrag() |
||||
drag.setData(pixmap) |
||||
drag.setPixmap(pixmap) |
||||
ttk.TTkLog.debug(f"Drag ({self.title()}) -> pos={evt.x},{evt.y}") |
||||
# Start the drag operation |
||||
drag.exec() |
||||
return True |
||||
|
||||
def dropEvent(self, evt:ttk.TTkDnDEvent) -> bool: |
||||
# When a drop event is received, the pixmap is stored in the list |
||||
self.pixmaps.append((evt.x, evt.y, evt.data())) |
||||
ttk.TTkLog.debug(f"Drop ({self.title()}) <- pos={evt.x},{evt.y}") |
||||
self.update() |
||||
return True |
||||
|
||||
def paintEvent(self, canvas:ttk.TTkCanvas) -> None: |
||||
_,_,w,h = self.geometry() |
||||
# Draw all the pixmaps on the canvas |
||||
for x,y,pixmap in self.pixmaps: |
||||
canvas.paintCanvas(pixmap, (x,y,w,h), (0,0,w,h), (0,0,w,h)) |
||||
# Call the base paintEvent to draw the frame on top of the pixmap |
||||
super().paintEvent(canvas) |
||||
|
||||
# Create the root application |
||||
# and set its layout to TTkGridLayout in order to |
||||
# place the widgets in the following way: |
||||
# |
||||
# Col 0 Col 1 |
||||
# +----------------+----------------+ |
||||
# Row 0 | DragDrop 1 | DragDrop 2 | |
||||
# + +----------------+ |
||||
# Row 1 | | DragDrop 3 | |
||||
# +----------------+----------------+ |
||||
# Row 2 | Log Viewer | |
||||
# +----------------+----------------+ |
||||
# |
||||
root = ttk.TTk() |
||||
root.setLayout(ttk.TTkGridLayout()) |
||||
|
||||
# Add the DragDrop widgets to the root layout |
||||
root.layout().addWidget(DragDrop(title="DnD 1"),0,0,2,1) |
||||
root.layout().addWidget(DragDrop(title="DnD 2"),0,1,1,1) |
||||
root.layout().addWidget(DragDrop(title="DnD 3"),1,1,1,1) |
||||
|
||||
# Add a LogViewer at the bottom to display the log messages |
||||
# (Row 2, Col 0, RowSpan 1, ColSpan 2) |
||||
root.layout().addWidget(ttk.TTkLogViewer(follow=True),2,0,1,2) |
||||
|
||||
root.mainloop() |
||||
@ -0,0 +1,119 @@
|
||||
#!/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 json |
||||
import random |
||||
|
||||
# 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 example is another showcase of the Drag Pixmap; |
||||
# It is basically a lazy collection of the previous examples |
||||
# No drop routine is implemented in this example. |
||||
|
||||
imagesFile = os.path.join(os.path.dirname(os.path.abspath(__file__)),'../ansi.images.json') |
||||
with open(imagesFile) as f: |
||||
d = json.load(f) |
||||
# Image exported by the Dumb Paint Tool - Removing the extra '\n' at the end |
||||
diamond = ttk.TTkString(ttk.TTkUtil.base64_deflate_2_obj(d['compressed']['diamond' ])[0:-1]) |
||||
fire = ttk.TTkString(ttk.TTkUtil.base64_deflate_2_obj(d['compressed']['fire' ])[0:-1]) |
||||
key = ttk.TTkString(ttk.TTkUtil.base64_deflate_2_obj(d['compressed']['key' ])[0:-1]) |
||||
peach = ttk.TTkString(ttk.TTkUtil.base64_deflate_2_obj(d['compressed']['peach' ])[0:-1]) |
||||
pepper = ttk.TTkString(ttk.TTkUtil.base64_deflate_2_obj(d['compressed']['pepper' ])[0:-1]) |
||||
python = ttk.TTkString(ttk.TTkUtil.base64_deflate_2_obj(d['compressed']['python' ])[0:-1]) |
||||
ring = ttk.TTkString(ttk.TTkUtil.base64_deflate_2_obj(d['compressed']['ring' ])[0:-1]) |
||||
sword = ttk.TTkString(ttk.TTkUtil.base64_deflate_2_obj(d['compressed']['sword' ])[0:-1]) |
||||
whip = ttk.TTkString(ttk.TTkUtil.base64_deflate_2_obj(d['compressed']['whip' ])[0:-1]) |
||||
|
||||
def imageSize(img:ttk.TTkString) -> int: |
||||
lines = img.split('\n') |
||||
return ( |
||||
max(line.termWidth() for line in lines), |
||||
len(lines)) |
||||
|
||||
class DragDropBase(ttk.TTkFrame): |
||||
def mouseDragEvent(self, evt:ttk. TTkMouseEvent) -> bool: |
||||
drag = ttk.TTkDrag() |
||||
drag.exec() |
||||
return True |
||||
|
||||
class DragDropWidget(ttk.TTkFrame): |
||||
def mouseDragEvent(self, evt:ttk. TTkMouseEvent) -> bool: |
||||
button = ttk.TTkButton(text=f"DnD: ({self.title()})", border=True, size=(25,5)) |
||||
drag = ttk.TTkDrag() |
||||
drag.setPixmap(button) |
||||
drag.exec() |
||||
return True |
||||
|
||||
class DragDropTxt(ttk.TTkFrame): |
||||
def mouseDragEvent(self, evt:ttk. TTkMouseEvent) -> bool: |
||||
pixmap = ttk.TTkCanvas(width=17,height=5) |
||||
pixmap.drawText(pos=(0,0),text="╭╼ TXT ╾────────╮") |
||||
pixmap.drawText(pos=(0,1),text="│Lorem ipsum dol│") |
||||
pixmap.drawText(pos=(0,2),text="│consectetur adi│") |
||||
pixmap.drawText(pos=(0,3),text="│sed do eiusmod │") |
||||
|
||||
# The next condition is meant to show that you can |
||||
# handle also the Drag and Drop with the Right or Middle mouse buttons. |
||||
if evt.key == ttk. TTkMouseEvent.LeftButton: |
||||
pixmap.drawText(pos=(0,4),text="╰───────╼ Left ╾╯") |
||||
elif evt.key == ttk. TTkMouseEvent.RightButton: |
||||
pixmap.drawText(pos=(0,4),text="╰──────╼ Right ╾╯") |
||||
elif evt.key == ttk. TTkMouseEvent.MidButton: |
||||
pixmap.drawText(pos=(0,4),text="╰────╼ Eugenio ╾╯") |
||||
|
||||
drag = ttk.TTkDrag() |
||||
drag.setPixmap(pixmap) |
||||
drag.exec() |
||||
return True |
||||
|
||||
class DragDropImg(ttk.TTkFrame): |
||||
def mouseDragEvent(self, evt:ttk. TTkMouseEvent) -> bool: |
||||
if evt.key == ttk. TTkMouseEvent.LeftButton: |
||||
imageString = random.choice([diamond,fire,key,peach,ring,sword,whip,pepper,python]) |
||||
|
||||
# A canvas is created and the ANSI String is drawn on it line by line |
||||
w,h = imageSize(imageString) |
||||
pixmap = ttk.TTkCanvas(width=w, height=h+1) |
||||
pixmap.setTransparent(True) |
||||
pixmap.drawText(pos=(0,0), text=self.title()) |
||||
for y,line in enumerate(imageString.split('\n')): |
||||
pixmap.drawTTkString(pos=(0,y+1), text=line) |
||||
|
||||
drag = ttk.TTkDrag() |
||||
drag.setPixmap(pixmap) |
||||
drag.exec() |
||||
return True |
||||
|
||||
root = ttk.TTk() |
||||
|
||||
root.layout().addWidget(DragDropBase( pos=( 0, 0), size=(25,10), title="Pixmap: Default")) |
||||
root.layout().addWidget(DragDropWidget(pos=( 0, 10), size=(25,10), title="Pixmap: Widget")) |
||||
root.layout().addWidget(DragDropTxt( pos=(50, 0), size=(25,10), title="Pixmap: Txt")) |
||||
root.layout().addWidget(DragDropImg( pos=(50, 10), size=(25,10), title="Pixmap: Img")) |
||||
|
||||
root.mainloop() |
||||
@ -0,0 +1,125 @@
|
||||
#!/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. |
||||
|
||||
# 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 example show the basic Drag and Drop pixmap usage; |
||||
# |
||||
# Anytime a Drag and Drop operation is started, a new TTkButton is created |
||||
# the hotSpot is set to define the offset from the mouse cursor |
||||
|
||||
class DraggableFrame_FixedHotSpot(ttk.TTkFrame): |
||||
# I save the hotSpot in the constructor to be used during the dragging operation |
||||
def __init__(self, *, hotSpot ,**kwargs): |
||||
self.hotSpot = hotSpot |
||||
super().__init__(**kwargs) |
||||
self.layout().addWidget(ttk.TTkLabel(text="Drag Me...")) |
||||
|
||||
def mouseDragEvent(self, evt:ttk. TTkMouseEvent) -> bool: |
||||
button = ttk.TTkButton(text=f"{self.title()}", border=True, size=self.size()) |
||||
drag = ttk.TTkDrag() |
||||
drag.setHotSpot(self.hotSpot) |
||||
drag.setData(button) |
||||
drag.setPixmap(button) |
||||
ttk.TTkLog.debug(f"Drag ({self.title()}) -> {button.text()}, pos={evt.x},{evt.y}") |
||||
# Start the drag operation |
||||
drag.exec() |
||||
return True |
||||
|
||||
class DraggableFrame_RelativeHotSpot(ttk.TTkFrame): |
||||
def __init__(self, **kwargs): |
||||
super().__init__(**kwargs) |
||||
self.layout().addWidget(ttk.TTkLabel(text="Drag Me...")) |
||||
|
||||
def mouseDragEvent(self, evt:ttk. TTkMouseEvent) -> bool: |
||||
button = ttk.TTkButton(text=f"HotSpot at\nMouse relative Pos\n\n-->{(evt.x, evt.y)}<--", border=True, size=self.size()) |
||||
drag = ttk.TTkDrag() |
||||
drag.setHotSpot((evt.x, evt.y)) |
||||
drag.setData(button) |
||||
drag.setPixmap(self) |
||||
ttk.TTkLog.debug(f"Drag ({self.title()}) -> {button.text()}, pos={evt.x},{evt.y}") |
||||
# Start the drag operation |
||||
drag.exec() |
||||
return True |
||||
|
||||
class DropFrame(ttk.TTkFrame): |
||||
def dropEvent(self, evt:ttk.TTkDnDEvent) -> bool: |
||||
button:ttk.TTkButton = evt.data() |
||||
self.layout().addWidget(button) |
||||
# Since the frame by default has a padding of 1 |
||||
# I align the button to the mouse coordinates by subtracting the Top/Left padding size |
||||
t,b,l,r = self.getPadding() |
||||
hsx,hsy = evt.hotSpot() |
||||
button.move(evt.x-l-hsx, evt.y-t-hsy) |
||||
ttk.TTkLog.debug(f"Drop ({self.title()}) <- {button.text()}, pos={evt.x},{evt.y}") |
||||
|
||||
# This is not required in this example |
||||
# |
||||
# But I just add a logging feedback to the button |
||||
# To show that the button has been clicked |
||||
# Note: I highly recommend to avoid using lambda as a slot |
||||
# The correct way is to have a method in the class, marked as pyTTkSlot, |
||||
# capable of handling the signal |
||||
button.clicked.connect(lambda: ttk.TTkLog.debug(f"Clicked: {button.text()}")) |
||||
return True |
||||
|
||||
# Create the root application |
||||
# and set its layout to TTkGridLayout in order to |
||||
# place the widgets in the following way: |
||||
# |
||||
# Col 0 Col 1 |
||||
# +----------------+----------------+ |
||||
# Row 0 | DragDrop 1 | DragDrop 2 | |
||||
# + +----------------+ |
||||
# Row 1 | | DragDrop 3 | |
||||
# +----------------+----------------+ |
||||
# Row 2 | Log Viewer | |
||||
# +----------------+----------------+ |
||||
# |
||||
root = ttk.TTk() |
||||
root.setLayout(ttk.TTkGridLayout()) |
||||
|
||||
# Add the DragDrop widgets to the root layout |
||||
root.layout().addWidget(df1 := DropFrame(title="DnD 1"),0,0,2,1) |
||||
root.layout().addWidget( DropFrame(title="DnD 2"),0,1,1,1) |
||||
root.layout().addWidget( DropFrame(title="DnD 3"),1,1,1,1) |
||||
|
||||
df1.layout().addWidget(DraggableFrame_FixedHotSpot(pos=( 0, 0),size=(25,5),title="Fix HotSpot ( 0, 0)", hotSpot=( 0, 0))) |
||||
df1.layout().addWidget(DraggableFrame_FixedHotSpot(pos=( 0, 5),size=(25,5),title="Fix HotSpot ( 5, 0)", hotSpot=( 5, 0))) |
||||
df1.layout().addWidget(DraggableFrame_FixedHotSpot(pos=( 0,10),size=(25,5),title="Fix HotSpot ( 0, 3)", hotSpot=( 0, 3))) |
||||
df1.layout().addWidget(DraggableFrame_FixedHotSpot(pos=( 0,15),size=(25,5),title="Fix HotSpot ( 5, 3)", hotSpot=( 5, 3))) |
||||
df1.layout().addWidget(DraggableFrame_FixedHotSpot(pos=(25,10),size=(25,5),title="Fix HotSpot (-5,-3)", hotSpot=(-5,-3))) |
||||
df1.layout().addWidget(DraggableFrame_FixedHotSpot(pos=(25,15),size=(25,5),title="Fix HotSpot (10, 3)", hotSpot=(10, 3))) |
||||
|
||||
df1.layout().addWidget(DraggableFrame_RelativeHotSpot(pos=(25,0),size=(25,10),title="Relative HotSpot")) |
||||
|
||||
# Add a LogViewer at the bottom to display the log messages |
||||
# (Row 2, Col 0, RowSpan 1, ColSpan 2) |
||||
root.layout().addWidget(ttk.TTkLogViewer(follow=True),2,0,1,2) |
||||
|
||||
root.mainloop() |
||||
@ -0,0 +1,17 @@
|
||||
{ |
||||
"compressed":{ |
||||
"Note1:" : "HEX Codes thanks to: https://github.com/ceccopierangiolieugenio/pyTermTk/tree/main/tools/dumbPaintTool", |
||||
"pepper" : "eJx9Vk1yFjsMfAtW4QhsOMEr/49dughVnCF3CFUsWGTBAsJ7QOBunIRuyZ6xHUgg7u/zKJLVkltz9+Lzh5f/6M+bd/jw6q27fY0foMQqQZKX7KXd/np4PPeOKs1L9Nj8fm0GqdE2/6eXm+7qNAhFvMcKg/eX+yK5SYyS+C0mCTBco5Um9ZAczIR/gAcZJnenifdJPP64dqPipTjJaTGqTbyLPKc5apIznsDmv9kGmwinJiHzZP5YTuxDkiMTlu2MJWFdNh3/YefhZttSbi4SsDissPx5xTmQU6iKaSRZEmGzw288FLsd8qBdgN23xY4UDLOGJB1WGH29jFBCH52iOcN2LYQlaIhZgneKRhWJQlMA18o0nCRFRXNYcFRXib1ThiGZLopmGJrQduuGED1OlxTNDt3oXSIukZv2bltJGAW5e74g7KUcFSwGvory/jgdOAvP3DoDiBeDxZvSP5w2y+F60+FzxQqj+8koamGPM3N8YPFJ5ccrc7Lms6LZoZwHa9WWmMGDtdgUrTbO874CNjswGbxiGhmRzLZdLlSlFAW7XJWXtNQ1BzQdYhIsJgQBS7fpYvCkDBeboK5ySfPjj5N7VLwpqMWBFJE8W+jLZYTbHQ4FNYKwgK5Mdn5cRlAz9IWCkR30kutZp4CV+qHQ21bbCbByAzKgSArWKIkPAFuFHQXsbAP0DcSixfX46GieZDR2pshg3TxJV6SHSWSn7HTZuAOzTsHqh7RQ0bQaoX2LgSWSD6NpozhqBh1IuVNdd27VpFasRGV0aqLeAlZvtQriEDp7qEUhrDnjxLgbhF4yHQeANSiCZGexnvEGZUPTD32jZktIS58+aVONMXXmRDhGBb2dNw3VCVvrcqYcCmk0IFsk+81MJcSPEeYxwyobbgzUIQLoClcUu52zDnSbWEQrzrgMHkZJYWEjOHbGoXiJRehiMdXARrAfmdIdh87mrlJmuPbhocvz5D7+nVyct3ExZ3i6UVai3cmRIl8vqJGbWWuC/4Quc07vQFsVKAS2e1Q8mc3hKbPUIeYZJn8ckervfmluzrOzuSGtnCnbmOI8TB2suVUHAYu3whcBGTKDL1IXWl8/FdcpRrJl4XGaZBgowaayCQ/nPdaNbMf3BYVTN13XzXmogJ3UFNMoEpWsbMMs0bYqWt95OivE5Y3MQ8UZNw9/uLF8BQjry51qf760Hy+NFLm2TH/y7M6GSiAibSTOUno27xWFF43XbdkcpdnfPqjwGzlVkGD9U2363u3Np39/A7RA/Jk=" , |
||||
"python" : "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" , |
||||
|
||||
"Note2:" : "Icons from: https://valletyh.itch.io/icon-pack", |
||||
"fire" : "eJytlUsOgyAQhrvoovEKbjhBg/iohoO0iUlv4B1c9AhtD9iTFMHwGAbBh9HEDP8Mw8cMjOfP83KSz+MufvKeDnlftpzxomOc8rIZft+XMPPKMRICZGqc1TWvK/EKrxHzIimO+p0iYMkMGUzyuAxTvAKKglFOLYW2WZJW/DVQI43Hx2E180WMdu5kKZGWiM37sZmjtq0CoJaRDMDUExwkNhtpsiXygwShKiUVbEm3NrSlKyEnIoRbj9dHmIFPUA0Rl6H6Vs5iMfSZkH3Nsr56Z4Nxti1zro5J1xICZ7HCsNrZ26IYB+sEDTSeq8AORpxUPFYw56kBYmvH6hhANHwiuoRYGEaYE4o6YTtMv8dY47Cx63DpDlvYFP9IdGffWCBoekP2vv4BVO4f6w==" , |
||||
"fireMini" : "eJylk01OAzEMhVl0xRW4A4rtJJPIF0HiDL1DFyxZsIBShLgPO+7ASXjOJPPTCXRBq1Zp/Y3t9xwfdi9fu6vyuvvE4ebe7fFRScpKQ1IcRb39ijjT/vv4OsXZeXxLHuPZGzCAeJgJIiWnnisSS9Y14oIlGUYiBUvi1wQ6GEQ5VEQMCWskBNSRqddcmLRlKKpvjImjvGL6io/myvWf0BwspSWOQWdvZHhaiIlFbAUoGyJhzVinaI+rKczwD1Zv9XDwcIsqFgSPBRW3nlLhEGqDGtNHzZ10iDSfyx/4IUO1YNEcSrKfMWjmCOrtgg2PZ0Ze8spKJZRytZQpwDlvqCZpbhxXjn2XMy9mLpAZA/BwBqK9QAuQ0ujEaTHKhAsFLrUxkY2WzIn3RTZSDJkb5PCQ11Ly9H+7frmUoWb4WGxitpFJtTJlu7a00U220m2hyy5Khxmm6XcZ6wJ12r6WPXNniC9C2ipypxtXNqOuQKYt0Zd8KqY93/4AlgU7wQ==", |
||||
"key" : "eJzFVLsRwjAMpYCGFWgyAedPPua0CHfM4B1SMAKwHF0mQYkTHDuW45gCXwpLeZKefm73z+6wG871jZfTjenCHLyCVCBAVBXwukZBd697QA3lJAvBQDGEtfi5yEsKklcKOEOEGEPpo2UUjWz869GZH8Y39sh8s7PGXHBQDchGz0x5jfoGFhAqqvVm8yqmrBZ/qEzJymVk6hon9DHHm1GPsKlmbnW31CNpEDOY9bIsIYDqtQT9EMgZBAe3MjBB0HwFiM1oZ5sRKMOGNU2vjqelt4Lg7+Vu6NOL/7fWJrUs0v/ojOv4+7Li9rdxeZw/gO97Ug==", |
||||
"sword" : "eJzFU8kNwjAQ5AEfWuCTCpDXcXxoG0GihvTAgxKAAvnRBevElo/YJogHUVaKNpPZmfHmsr2/dpvpOj3p4XBmIxUKjRxhkAiKIWgYO9vts+4M48Pga3w+LgHIFAJQCcfHe6AioFA1IPWvVsPeC5kBxACCxsp0QkToFNeAQWJbyoKxZc70JNsRgjYIxiBnsoJLrHXdH8xFGj8fyE/mVthbiEm3oJVDTc1iMdfai/a8ac/PISiIKG9lX4DKNwTQkB2jyqiQVZxWJYSFtwzY/u9qO5wbCZLTE/DKAx1I4s5TjT6+Vg1+npml1fh2ZfBlvZwiknRzp0MOKA3KbKd812+UXT1mI05hXCNNKzPFOaRnXUzbcZVlfOUg63aTltvxDd6kgOU=", |
||||
"ring" : "eJylVcFtwzAM7KOPIiv0owkKU7JqCXxkjQCdwTvkkRHaDphJoji2LJGUrMQBHATkmeSdTsz5/e/48TZ9Ti78+PzpRqXCNxqHGjsEY1BDN17/L0k0RBC8y6LgBgTwaAF7ijpXUGuHMkobGyoBQjfUcdog2PD4Auw+8WPo8TBx5VRr08fo3M7a5clgSVxg+ULBpuG07YNQHp0WRcuga2ppvLy78xzGVN17vid5VeIuO0GQUj6YTCCi40sFG4bLaCfh3mCoDkB7D4DfAzo/i5LC1vmihR+o5Z3qudBSLfJzD8iXh0krOoUZuQnV1JGpHDaUSpbUhqq5iqokyiQZy8QdsUtHKslaMb1QSZ/IQXG6MSn7Yz9dteVvxrjg5Po+enqJ57xLd49uIn4lL2KiWc2mYeZ/F7UtZkG7RonJspDNL9qW3JpnhhPY/n7dAHoxGOQ=", |
||||
"diamond" : "eJyVlU1uhDAMhbuoVKlX6MbddVXFhDAgX6RSz8AdWPQIbQ/YkzQwgbwkjgIjZpgxH/55Np7l8eft6WF7fbz6Ly+fZiYifxI7SifWCU9GOufmv98vxSz9+pvdJF0/BG45OGeF+SadHe7cekN4rxyi/oON92JvKnpwRoZeeHRXKGafr2OF6tlfHENt8/NWvpJSUnxeVK14sFfTKIqgaDXWx5juVmgJeClBdIvhottdGahzlyEDmkodPkEoul5+kadeZk1mUC9kgzMLXJSpNoxJ9wqZ1dnNNCUUOkhGu2CZvSHf2foLneN8JjKDOSYJWpFKQkIDb0m14gDXClSg2rMLjK75JcVrj3d9Z53F9KkrulPhGkslH868F6VXVfWzN+scLAF1Myxxh1JT5rTLKYTHmcWVx25Hz/9tcOlpWR4Rvt//AVu00Dg=", |
||||
"peach" : "eJytVEtuhTAM7KKL6l2hm6i7bioCIR/5Ik96Z+AOLHqEtgfsSRogIYmxXfpUhAQME8ceTzw/fr4+PazX9SW+PN+6SSkVHzB46KEfR9BmAD3q6fvrvcW1BeMXuP6jgwcLFsNLDD9C10bpYnADXQyTYvbxU7shsmaGpXsLvTYQgkCqdpt5lvMQHLgxBZouv/FWdc5ps+GlMO0CeJTyDpP149R3xeWgrA5NpLQPJymGS9EFFHbIICnzRqG0n+6UNvuwpF6Joxow65s8TpIp0xkXXw92ykUcSEWuDUuE/WhUIqdFCi9JdRdhDBZGid6wy330mywe68vSDNKXZ1uywX9NPOmWKEPsYIh3m3NGBaUTpkjtKQNWiWEPo2zxxORKouVbf/9XdZWv91hSyXzm5LnF+TbNFnJmLMkWxnburCNaCnsg2FokyY5jQpptjC+olfe04AyHGk14L2F8lYZMl4+3HxigIEs=", |
||||
"whip" : "eJylU8ERwiAQ9KGftOCHChyPhEDmnv6swBlroAcelqAWaCViQHIQCBNlyCRzt7e3CxezfZx3m3FdTvZjfz1qxph9YauQIwdAUC2CEPr1vMVxYeOdnMcD3hTwhqZADQjQ2Qd0IY7dGOglysHuEqyiUDfOXU6s65Co9IfBSpyelgCqEtc5GRXPk2nTn+nz1jxJ/VrieNp0xsLS4aoKz/tPsTPavy6BRG+ls4tStCAMzXQAIV0WSG2mrvyaALxDwe0m7dxcB0g/oBIoVORgEFZ8iyr+Sb5Qr/XjsAeUMjqSUJpDLQCJDpPVb0K9s1CQRaUToiBjqZuQdrIdeAUq3zFbm0J1cz+8AbE/aBQ=" |
||||
} |
||||
} |
||||
Loading…
Reference in new issue