diff --git a/.vscode/launch.json b/.vscode/launch.json index 4bfe97d4..090d969e 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -41,6 +41,14 @@ "program": "tools/dumb.paint.tool.py", "console": "integratedTerminal", "justMyCode": true + },{ + "name": "Python: DumbPaintTool File", + "type": "debugpy", + "request": "launch", + "program": "tools/dumb.paint.tool.py", + "console": "integratedTerminal", + "justMyCode": true, + "args":["experiments/paint.test.json"] },{ "name": "Python: Demo", "type": "debugpy", diff --git a/README.md b/README.md index 47c8688f..1cc81ac9 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,7 @@ python3 tests/test.ui.018.TextEdit.Pygments.py README.md - [pytest-fold](https://github.com/jeffwright13/pytest-fold) - A Pytest plugin to make console output more manageable when there are multiple failed tests - [pytest-tui](https://github.com/jeffwright13/pytest-tui) - A Text User Interface (TUI) for Pytest, automatically launched after your test run is finished - [breakoutRL](https://ceccopierangiolieugenio.itch.io/breakoutrl) - Breakout the Roguelike +- [7drl-2024](https://ceccopierangiolieugenio.itch.io/a-snake-on-a-plane) - A Snake🐍 on a Plane✈️ - The Roguelike ## Related Projects - Honourable mention diff --git a/TermTk/TTkCore/TTkTerm/input_thread.py b/TermTk/TTkCore/TTkTerm/input_thread.py index 2e0808a9..216be61a 100644 --- a/TermTk/TTkCore/TTkTerm/input_thread.py +++ b/TermTk/TTkCore/TTkTerm/input_thread.py @@ -111,20 +111,24 @@ class TTkInput: TTkInput._inputQueue.put(outq) TTkInput._inputQueue.put(None) + @staticmethod + def _handleBracketedPaste(stdinRead:str): + if stdinRead.endswith("\033[201~"): + TTkInput._pasteBuffer += stdinRead[:-6] + TTkInput._bracketedPaste = False + # due to the CRNL methos (don't ask me why) the terminal + # is substituting all the \n with \r + _paste = TTkInput._pasteBuffer.replace('\r','\n') + TTkInput._pasteBuffer = "" + return None, None, _paste + else: + TTkInput._pasteBuffer += stdinRead + return None, None, None + @staticmethod def key_process(stdinRead:str) -> None: if TTkInput._bracketedPaste: - if stdinRead.endswith("\033[201~"): - TTkInput._pasteBuffer += stdinRead[:-6] - TTkInput._bracketedPaste = False - # due to the CRNL methos (don't ask me why) the terminal - # is substituting all the \n with \r - _paste = TTkInput._pasteBuffer.replace('\r','\n') - TTkInput._pasteBuffer = "" - return None, None, _paste - else: - TTkInput._pasteBuffer += stdinRead - return None, None, None + return TTkInput._handleBracketedPaste(stdinRead) mevt,kevt = None,None @@ -205,9 +209,8 @@ class TTkInput: return kevt, mevt, None if stdinRead.startswith("\033[200~"): - TTkInput._pasteBuffer = stdinRead[6:] TTkInput._bracketedPaste = True - return None, None, None + return TTkInput._handleBracketedPaste(stdinRead[6:]) hex = [f"0x{ord(x):02x}" for x in stdinRead] TTkLog.error("UNHANDLED: "+stdinRead.replace("\033","") + " - "+",".join(hex)) diff --git a/TermTk/TTkCore/signal.py b/TermTk/TTkCore/signal.py index ea3a3142..25b2054b 100644 --- a/TermTk/TTkCore/signal.py +++ b/TermTk/TTkCore/signal.py @@ -123,7 +123,7 @@ class _pyTTkSignal_obj(): raise TypeError(error) else: for a,b in zip(slot._TTkslot_attr, self._types): - if not issubclass(a,b): + if a!=b and not issubclass(a,b): error = "Decorated slot has no signature compatible: "+slot.__name__+str(slot._TTkslot_attr)+" != signal"+str(self._types) raise TypeError(error) if slot not in self._connected_slots: diff --git a/TermTk/TTkGui/clipboard.py b/TermTk/TTkGui/clipboard.py index 4ce0f173..07e5b022 100644 --- a/TermTk/TTkGui/clipboard.py +++ b/TermTk/TTkGui/clipboard.py @@ -59,7 +59,13 @@ class TTkClipboard(): @staticmethod def _loadClipboardManager(): try: - if importlib.util.find_spec('copykitten'): + if importlib.util.find_spec('pyodideProxy'): + TTkLog.info("Using 'pyodideProxy' as clipboard manager") + import pyodideProxy as _c + TTkClipboard._manager = _c + TTkClipboard._setText = _c.copy + TTkClipboard._text = _c.paste + elif importlib.util.find_spec('copykitten'): TTkLog.info("Using 'copykitten' as clipboard manager") import copykitten as _c TTkClipboard._manager = _c @@ -113,9 +119,14 @@ class TTkClipboard(): def text(): '''text''' if TTkClipboard._text: - txt = TTkClipboard._text() - if txt == str(TTkClipboard._clipboard): + txt = "" + try: + txt = TTkClipboard._text() + except Exception as e: + TTkLog.error("Clipboard error, try to export X11 if you are running this UI via SSH") + for line in str(e).split("\n"): + TTkLog.error(line) + if txt == None or txt == str(TTkClipboard._clipboard): return TTkClipboard._clipboard - else: - return TTkClipboard._text() + return txt return TTkClipboard._clipboard diff --git a/tests/sandbox/clipbboard.test.html b/tests/sandbox/clipbboard.test.html new file mode 100644 index 00000000..ed5f1d5d --- /dev/null +++ b/tests/sandbox/clipbboard.test.html @@ -0,0 +1,84 @@ + + + + + +Clipboard Test + + + +

Clipboard Test

+ +

Click the button below to copy the text to your clipboard:

+ + + + + +
+ +
+ +

+ + + + \ No newline at end of file diff --git a/tests/sandbox/js b/tests/sandbox/js new file mode 120000 index 00000000..b0a546f3 --- /dev/null +++ b/tests/sandbox/js @@ -0,0 +1 @@ +../../tools/webExporter/js \ No newline at end of file diff --git a/tools/webExporter/index.html b/tools/webExporter/index.html new file mode 100644 index 00000000..0545777f --- /dev/null +++ b/tools/webExporter/index.html @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + +
+ + + + + diff --git a/tests/sandbox/js/ttkproxy.js b/tools/webExporter/js/ttkproxy.js similarity index 90% rename from tests/sandbox/js/ttkproxy.js rename to tools/webExporter/js/ttkproxy.js index b62be65e..04d4151b 100644 --- a/tests/sandbox/js/ttkproxy.js +++ b/tools/webExporter/js/ttkproxy.js @@ -29,6 +29,32 @@ class TTkProxy { } pyodideProxy = { + copy: function(text){ + console.log("Copying:",text) + if(navigator.clipboard){ + navigator.clipboard.writeText(text) + return //codes below wont be executed + } + const textArea = document.createElement("textarea") + textArea.value = text + + document.body.appendChild(textArea) + + textArea.focus() + textArea.select() + + document.execCommand('copy') + + document.body.removeChild(textArea) + }, + paste: function(){ + if(navigator.clipboard){ + text = navigator.clipboard.readText() + console.log("Pasted:",text) + return text + } + return null + }, consoleLog: function(m){ console.log("TTk:",m) }, diff --git a/tools/webExporter/package.json b/tools/webExporter/package.json new file mode 100644 index 00000000..207a13b6 --- /dev/null +++ b/tools/webExporter/package.json @@ -0,0 +1,10 @@ +{ + "libs" : [ + {"pkg" :"bin/TermTk.tgz", + "name": "TermTk"}, + {"pkg" :"bin/dpt.tgz", + "name": "Dumb Paint Tool"} + ], + "mainOld": "main.py", + "main": "dumb.paint.tool.py" +} diff --git a/tools/webExporterInit.sh b/tools/webExporterInit.sh new file mode 100755 index 00000000..3b2cc0f3 --- /dev/null +++ b/tools/webExporterInit.sh @@ -0,0 +1,115 @@ +#!/usr/bin/env bash + +# 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. + + +_PWD=`pwd` +_TOOLS_BASE_PATH=$(dirname $(readlink -f $0)) +_BASE_PATH=$( readlink -f ${_TOOLS_BASE_PATH}/.. ) +_TMP_PATH=$( readlink -f ${_BASE_PATH}/tmp ) + +_MAJOR=$( git describe --tags | sed 's,\([0-9]*\)\..*,\1,' ) +_MINOR=$( git describe --tags | sed 's,[0-9]*\.\([0-9]*\)\..*,\1,' ) +_PATCH=$( git describe --tags | sed 's,[0-9]*\.[0-9]*\.\([0-9]*\)[^0-9].*,\1,' ) +_STAGE=$( git describe --tags | sed 's,[^-]*-a-\?\([0-9]*\).*,\1,' ) + +_VERSION="${_MAJOR}.${_MINOR}.${_PATCH}-a${_STAGE}" +_DOCVERSION="${_MAJOR}.${_MINOR}.${_PATCH}-a" + +echo Version: ${_VERSION} +echo Name: ${_NAME} + +mkdir -p ${_TMP_PATH} +rm -rf ${_TMP_PATH}/* itchExport.zip + +${_TOOLS_BASE_PATH}/prepareBuild.sh release + +mkdir -p ${_TMP_PATH}/bin \ + ${_TMP_PATH}/www/pyodide \ + ${_TMP_PATH}/www/xterm/ \ + ${_TMP_PATH}/www/xterm-addon-fit \ + ${_TMP_PATH}/www/xterm-addon-unicode11 \ + ${_TMP_PATH}/www/webfonts \ + ${_TMP_PATH}/www/nerdfonts \ + ${_TMP_PATH}/www/opentype + +function _download { + _P=$1 + _F=$2 + if [ -f tests/sandbox/${_F} ] ; + then cp tests/sandbox/${_F} ${_P} ; + else wget -P ${_P} https://ceccopierangiolieugenio.github.io/binaryRepo/pyTermTk/${_F}; + fi ; +}; + +_download ${_TMP_PATH}/www/pyodide/ www/pyodide/pyodide.js +# _download ${_TMP_PATH}/www/pyodide/ www/pyodide/pyodide.js +_download ${_TMP_PATH}/www/pyodide/ www/pyodide/pyodide-lock.json +_download ${_TMP_PATH}/www/pyodide/ www/pyodide/python_stdlib.zip +_download ${_TMP_PATH}/www/pyodide/ www/pyodide/pyodide.asm.js +_download ${_TMP_PATH}/www/pyodide/ www/pyodide/repodata.json +_download ${_TMP_PATH}/www/pyodide/ www/pyodide/pyodide.asm.wasm + +_download ${_TMP_PATH}/www/xterm/ www/xterm/xterm.css +_download ${_TMP_PATH}/www/xterm/ www/xterm/xterm.js +_download ${_TMP_PATH}/www/xterm/ www/xterm/xterm.js.map + +_download ${_TMP_PATH}/www/xterm-addon-fit/ www/xterm-addon-fit/xterm-addon-fit.js +_download ${_TMP_PATH}/www/xterm-addon-fit/ www/xterm-addon-fit/xterm-addon-fit.js.map + +_download ${_TMP_PATH}/www/xterm-addon-unicode11/ www/xterm-addon-unicode11/xterm-addon-unicode11.js + +# _download ${_TMP_PATH}/www/webfonts/ www/webfonts/fa-regular-400.woff2 +# _download ${_TMP_PATH}/www/nerdfonts/ www/nerdfonts/HurmitNerdFontMono-Regular.otf +# _download ${_TMP_PATH}/www/nerdfonts/ www/nerdfonts/DejaVuSansMNerdFont-Regular.ttf +_download ${_TMP_PATH}/www/opentype/ www/opentype/3270SemiCondensed-Regular.otf + +_download ${_TMP_PATH}/www/ www/favicon.ico + + +tar cvzf ${_TMP_PATH}/bin/TermTk.tgz --exclude='__pycache__' --transform "s,^.*TermTk/,TermTk/," ${_TMP_PATH}/TermTk +tar cvzf ${_TMP_PATH}/bin/DPT.tgz --exclude='__pycache__' --transform "s,^.*/dumb,dumb," ${_TOOLS_BASE_PATH}/dumb.paint.tool.py ${_TOOLS_BASE_PATH}/dumb_paint_lib + +# find ${_TMP_PATH}/TermTk \ +# | grep -v __pycache__ | xargs tar cvzf ${_TMP_PATH}/bin/TermTk.tgz -C ${_TMP_PATH} +# +# find ${_TOOLS_BASE_PATH}/dumb.paint.tool.py ${_TOOLS_BASE_PATH}/dumb_paint_lib \ +# | grep -v __pycache__ | xargs tar cvzf ${_TMP_PATH}/bin/DPT.tgz -C ${_TOOLS_BASE_PATH} + +cp -a ${_TOOLS_BASE_PATH}/webExporter/* ${_TMP_PATH}/ + +echo '{ + "libs" : [ + {"pkg" :"bin/TermTk.tgz", + "name": "TermTk"}, + {"pkg" :"bin/DPT.tgz", + "name": "Dumb Paint Tool"} + ], + "mainOld": "main.py", + "main": "dumb.paint.tool.py" +}' > ${_TMP_PATH}/package.json + +rm -rf ${_TMP_PATH}/TermTk +pushd ${_TMP_PATH} +zip -r ${_PWD}/itchExport.zip * +popd \ No newline at end of file diff --git a/ttkDesigner/app/widgetbox.py b/ttkDesigner/app/widgetbox.py index 86544028..9019990d 100644 --- a/ttkDesigner/app/widgetbox.py +++ b/ttkDesigner/app/widgetbox.py @@ -65,6 +65,7 @@ dWidgets = { }, 'Pickers':{ "Color Picker" : { "class":ttk.TTkColorButtonPicker, "params":{'size':( 6,3), 'border':True}}, + "Color Picker Slim": { "class":ttk.TTkColorButtonPicker, "params":{'size':( 6,1), 'border':False}}, "File Picker" : { "class":ttk.TTkFileButtonPicker, "params":{'size':(20,3), 'border':True}}, "Date Picker" : { "class":ttk.TTkButton, "params":{'size':(20,3)}, "disabled": True}, "TtkString Picker" : { "class":ttk.TTkButton, "params":{'size':(20,3)}, "disabled": True},