From 8821a5cdafe56b6b431b0f3acf65cab82d3df5cd Mon Sep 17 00:00:00 2001 From: Eugenio Parodi Date: Tue, 24 Aug 2021 23:18:40 +0100 Subject: [PATCH] Added TTkImage, TTkAbout widgets --- TermTk/TTkWidgets/__init__.py | 2 + TermTk/TTkWidgets/about.py | 82 +++++++++++++++++ TermTk/TTkWidgets/image.py | 112 +++++++++++++++++++++++ TermTk/TTkWidgets/window.py | 9 +- demo/demo.py | 1 + demo/showcase/windows.py | 4 + tests/test.ui.016.about.py | 36 ++++++++ tests/test.ui.016.raster.py | 162 ++++++++++++++++++++++++++++++++++ 8 files changed, 407 insertions(+), 1 deletion(-) create mode 100644 TermTk/TTkWidgets/about.py create mode 100644 TermTk/TTkWidgets/image.py create mode 100755 tests/test.ui.016.about.py create mode 100755 tests/test.ui.016.raster.py diff --git a/TermTk/TTkWidgets/__init__.py b/TermTk/TTkWidgets/__init__.py index 80464243..bbe23191 100644 --- a/TermTk/TTkWidgets/__init__.py +++ b/TermTk/TTkWidgets/__init__.py @@ -25,3 +25,5 @@ from .graph import * from .menubar import * from .TTkPickers import * from .spinbox import * +from .image import TTkImage +from .about import TTkAbout diff --git a/TermTk/TTkWidgets/about.py b/TermTk/TTkWidgets/about.py new file mode 100644 index 00000000..09d95568 --- /dev/null +++ b/TermTk/TTkWidgets/about.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python3 + +# MIT License +# +# Copyright (c) 2021 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. + +from TermTk.TTkCore.log import TTkLog +from TermTk.TTkCore.cfg import TTkCfg +from TermTk.TTkCore.color import TTkColor +from TermTk.TTkCore.string import TTkString +from TermTk.TTkWidgets.window import TTkWindow +from TermTk.TTkWidgets.image import TTkImage + +class TTkAbout(TTkWindow): + peppered=[ + [(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x01,0x00),(0x39,0x61,0x00),(0x76,0x9e,0x17),(0x87,0x9f,0x3a),(0x3d,0x4c,0x14),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00)], + [(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x02,0x11,0x00),(0x21,0x44,0x01),(0x99,0xc1,0x33),(0x4e,0x71,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00)], + [(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x30,0x5e,0x0f),(0x71,0x9e,0x47),(0x69,0xa2,0x32),(0x8b,0xa8,0x65),(0xb0,0xc4,0x91),(0x97,0xb6,0x66),(0xa0,0xad,0x81),(0x5f,0x8e,0x38),(0x42,0x77,0x19),(0x08,0x21,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00)], + [(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x1b,0x00,0x00),(0x5b,0x00,0x00),(0x80,0x00,0x00),(0x6c,0x07,0x00),(0x35,0x29,0x00),(0x26,0x61,0x01),(0x5c,0x89,0x25),(0x76,0x73,0x28),(0x7e,0x67,0x1d),(0x54,0x6a,0x19),(0x3e,0x48,0x05),(0x9e,0x1b,0x18),(0xbe,0x40,0x40),(0xc7,0x3f,0x3f),(0xcc,0x1a,0x1b),(0xb1,0x00,0x00),(0x47,0x00,0x00)], + [(0x00,0x00,0x00),(0x83,0x00,0x00),(0xd6,0x43,0x43),(0xf5,0x94,0x93),(0xff,0x7f,0x7f),(0xfc,0x42,0x43),(0xc9,0x02,0x03),(0xb4,0x02,0x02),(0xdb,0x41,0x41),(0xf9,0x90,0x91),(0xff,0xce,0xd0),(0xff,0xc2,0xc2),(0xfd,0x7d,0x7d),(0xd8,0x28,0x2a),(0xab,0x4c,0x4d),(0xf4,0xcd,0xce),(0xff,0xad,0xae),(0xff,0x47,0x47),(0xef,0x00,0x00),(0x81,0x00,0x00)], + [(0x40,0x00,0x00),(0xf6,0x03,0x03),(0xff,0x6d,0x6d),(0xff,0xa5,0xa6),(0xfc,0x87,0x87),(0x8d,0x2d,0x2f),(0xe6,0x00,0x00),(0xff,0x0b,0x0d),(0xff,0x4a,0x49),(0xff,0x79,0x7a),(0xff,0x93,0x93),(0xff,0x8d,0x8d),(0xff,0x6b,0x6c),(0xff,0x34,0x34),(0xe5,0x00,0x00),(0x94,0x3d,0x3f),(0xff,0x41,0x42),(0xcd,0x02,0x01),(0x36,0x00,0x00),(0x00,0x00,0x00)], + [(0x5b,0x00,0x00),(0xe8,0x00,0x00),(0xfe,0x05,0x05),(0xff,0x10,0x10),(0xed,0x0f,0x0e),(0x66,0x00,0x00),(0xec,0x00,0x00),(0xff,0x00,0x00),(0xff,0x08,0x08),(0xff,0x21,0x21),(0xff,0x2f,0x30),(0xff,0x2e,0x2e),(0xff,0x1b,0x1b),(0xff,0x03,0x03),(0xfa,0x00,0x00),(0x5b,0x00,0x00),(0xd0,0x00,0x00),(0x24,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00)], + [(0x07,0x00,0x00),(0x56,0x00,0x00),(0x93,0x00,0x00),(0xb5,0x00,0x00),(0xca,0x00,0x00),(0x35,0x00,0x00),(0xa5,0x00,0x00),(0xeb,0x00,0x00),(0xfe,0x00,0x00),(0xff,0x00,0x00),(0xff,0x00,0x00),(0xff,0x00,0x00),(0xff,0x00,0x00),(0xfe,0x00,0x00),(0xd5,0x00,0x00),(0x3d,0x00,0x00),(0x6c,0x00,0x00),(0x02,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00)], + [(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x04,0x00,0x00),(0x40,0x00,0x00),(0x4d,0x00,0x00),(0x30,0x00,0x00),(0x84,0x00,0x00),(0xc3,0x00,0x00),(0xe7,0x00,0x00),(0xf3,0x00,0x00),(0xf5,0x00,0x00),(0xe6,0x00,0x00),(0xbb,0x00,0x00),(0x54,0x00,0x00),(0x8c,0x00,0x00),(0x6a,0x00,0x00),(0x06,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00)], + [(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x0c,0x00,0x00),(0x4e,0x00,0x00),(0x92,0x00,0x00),(0x8a,0x00,0x00),(0x41,0x00,0x00),(0x8a,0x00,0x00),(0xb9,0x00,0x00),(0xd5,0x00,0x00),(0xdf,0x00,0x00),(0xd2,0x00,0x00),(0x9d,0x00,0x00),(0x7e,0x00,0x00),(0xf7,0x00,0x00),(0xb8,0x00,0x00),(0x47,0x00,0x00),(0x03,0x00,0x00),(0x00,0x00,0x00)], + [(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x05,0x00,0x00),(0x50,0x00,0x00),(0xa1,0x00,0x00),(0xe7,0x00,0x00),(0xb0,0x00,0x00),(0x7e,0x00,0x00),(0xd4,0x00,0x00),(0xfa,0x00,0x00),(0xfe,0x00,0x00),(0xf6,0x00,0x00),(0x9f,0x00,0x00),(0xcd,0x00,0x00),(0xff,0x00,0x00),(0xeb,0x00,0x00),(0x9a,0x00,0x00),(0x35,0x00,0x00),(0x00,0x00,0x00)], + [(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x3c,0x00,0x00),(0xa0,0x00,0x00),(0xec,0x00,0x00),(0xfe,0x00,0x00),(0xbf,0x00,0x01),(0xb7,0x00,0x00),(0xfe,0x00,0x00),(0xff,0x00,0x00),(0xfb,0x00,0x00),(0x9d,0x02,0x02),(0xf8,0x12,0x13),(0xff,0x00,0x00),(0xf6,0x00,0x00),(0xb0,0x00,0x00),(0x43,0x00,0x00),(0x00,0x00,0x00)], + [(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x1d,0x00,0x00),(0x8b,0x00,0x00),(0xe7,0x00,0x00),(0xff,0x00,0x00),(0xff,0x06,0x08),(0xb4,0x0b,0x0d),(0xf4,0x00,0x00),(0xff,0x00,0x00),(0xfc,0x00,0x00),(0xb5,0x0d,0x0d),(0xff,0x1a,0x1b),(0xff,0x00,0x00),(0xf8,0x00,0x00),(0xaf,0x00,0x00),(0x3b,0x00,0x00),(0x00,0x00,0x00)], + [(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x04,0x00,0x00),(0x65,0x00,0x00),(0xd4,0x00,0x00),(0xff,0x00,0x00),(0xff,0x01,0x01),(0xd6,0x0c,0x0c),(0xe4,0x00,0x00),(0xff,0x1f,0x20),(0xff,0x0e,0x0e),(0xb8,0x02,0x02),(0xff,0x0a,0x0a),(0xff,0x00,0x00),(0xf4,0x00,0x00),(0xa3,0x00,0x00),(0x31,0x00,0x00),(0x01,0x00,0x00)], + [(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x40,0x00,0x00),(0xb3,0x00,0x00),(0xf7,0x00,0x00),(0xff,0x00,0x00),(0xea,0x00,0x01),(0xe4,0x00,0x00),(0xff,0x55,0x55),(0xff,0x49,0x49),(0xd2,0x00,0x00),(0xfc,0x00,0x00),(0xff,0x00,0x00),(0xe5,0x00,0x00),(0x94,0x00,0x00),(0x28,0x00,0x00),(0x01,0x00,0x00)], + [(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x1e,0x00,0x00),(0x88,0x00,0x00),(0xda,0x00,0x00),(0xfd,0x00,0x00),(0xea,0x00,0x00),(0xee,0x0a,0x0a),(0xff,0x97,0x98),(0xff,0xa0,0xa0),(0xee,0x11,0x11),(0xef,0x00,0x00),(0xf7,0x00,0x00),(0xc7,0x00,0x00),(0x7e,0x00,0x00),(0x1e,0x00,0x00),(0x00,0x00,0x00)], + [(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x04,0x00,0x00),(0x57,0x00,0x00),(0xaa,0x00,0x00),(0xde,0x00,0x00),(0xc9,0x00,0x00),(0xf8,0x19,0x19),(0xff,0xa9,0xa9),(0xff,0xbf,0xbf),(0xfb,0x29,0x2a),(0xcd,0x00,0x00),(0xd4,0x00,0x00),(0xa0,0x00,0x00),(0x5e,0x00,0x00),(0x0e,0x00,0x00),(0x00,0x00,0x00)], + [(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x21,0x00,0x00),(0x6c,0x00,0x00),(0xa2,0x00,0x00),(0x84,0x00,0x00),(0xe6,0x02,0x02),(0xff,0x3a,0x3a),(0xff,0x43,0x43),(0xec,0x05,0x04),(0x8f,0x00,0x00),(0x93,0x00,0x00),(0x65,0x00,0x00),(0x2b,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00)], + [(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x0b,0x00,0x00),(0x29,0x00,0x00),(0x30,0x00,0x00),(0x4c,0x00,0x00),(0x95,0x00,0x00),(0xa0,0x00,0x00),(0x61,0x00,0x00),(0x1a,0x00,0x00),(0x10,0x00,0x00),(0x03,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00)], + [(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00)]] + + pyTermTk = [ + " ████████╗ ████████╗ ", + " ╚══██╔══╝ ╚══██╔══╝ ", + " ██║ ▄▄ ▄ ▄▄ ▄▄▖▄▖ ██║ █ ▗▖ ", + " ▞▀▚ ▖▗ ██║ █▄▄█ █▀▘ █ █ █ ██║ █▟▘ ", + " ▙▄▞▐▄▟ ██║ ▀▄▄▖ █ █ ▝ █ ██║ █ ▀▄ ", + " ▌ ▐ ╚═╝ ╚═╝ ", + " ▚▄▄▘ "] + + __slots__=('_image') + def __init__(self, *args, **kwargs): + TTkWindow.__init__(self, *args, **kwargs) + self._name = kwargs.get('name' , 'TTkAbout' ) + self._image = TTkImage(parent=self, pos=(0,0), data=TTkAbout.peppered) + if not self.getTitle(): + self.setTitle('About...') + self.resize(55,15) + + def paintEvent(self): + c = [0xFF,0xFF,0xAA] + for y, line in enumerate(TTkAbout.pyTermTk): + self._canvas.drawText(pos=(9,3+y),text=line, color=TTkColor.fg(f'#{c[0]:02X}{c[1]:02X}{c[2]:02X}')) + c[2]-=0x11 + self._canvas.drawText(pos=(20,9),text=f" Version: {TTkCfg.version}", color=TTkColor.fg('#AAAAFF')) + self._canvas.drawText(pos=(12,11),text=f"Powered By, Eugenio Parodi") + self._canvas.drawText(pos=(2,13),text=f"https://github.com/ceccopierangiolieugenio/pyTermTk", color=TTkColor.fg('#44FFFF')) + + TTkWindow.paintEvent(self) diff --git a/TermTk/TTkWidgets/image.py b/TermTk/TTkWidgets/image.py new file mode 100644 index 00000000..a88adb08 --- /dev/null +++ b/TermTk/TTkWidgets/image.py @@ -0,0 +1,112 @@ +#!/usr/bin/env python3 + +# MIT License +# +# Copyright (c) 2021 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. + +from TermTk.TTkCore.log import TTkLog +from TermTk.TTkCore.color import TTkColor +from TermTk.TTkCore.string import TTkString +from TermTk.TTkWidgets.widget import TTkWidget + +class TTkImage(TTkWidget): + __slots__ = ('_data') + def __init__(self, *args, **kwargs): + TTkWidget.__init__(self, *args, **kwargs) + self._name = kwargs.get('name' , 'TTkImage' ) + self._data = kwargs.get('data' , [] ) + if self._data: + w = min([len(i) for i in self._data]) + h = len(self._data) + self.resize(w//2,h//2) + + def _reduce(self, a,b,c,d): + # quadblitter notcurses like + l = (a,b,c,d) + def delta(i): + return max([v[i] for v in l]) - min([v[i] for v in l]) + deltaR = delta(0) + deltaG = delta(1) + deltaB = delta(2) + + def midColor(c1,c2): + return ((c1[0]+c2[0])//2,(c1[1]+c2[1])//2,(c1[2]+c2[2])//2) + + def closer(a,b,c): + return \ + ( (a[0]-c[0])**2 + (a[1]-c[1])**2 + (a[2]-c[2])**2 ) > \ + ( (b[0]-c[0])**2 + (b[1]-c[1])**2 + (b[2]-c[2])**2 ) + + def splitReduce(i): + s = sorted(l,key=lambda x:x[i]) + mid = (s[3][i]+s[0][i])//2 + if s[1][i] < mid: + if s[2][i] > mid: + c1 = midColor(s[0],s[1]) + c2 = midColor(s[2],s[3]) + else: + c1 = midColor(s[0],s[1]) + c1 = midColor(c1,s[2]) + c2 = s[3] + else: + c1 = s[0] + c2 = midColor(s[1],s[2]) + c2 = midColor(c1,s[3]) + + + ch = 0x01 if closer(c1,c2,l[0]) else 0 + ch |= 0x02 if closer(c1,c2,l[1]) else 0 + ch |= 0x04 if closer(c1,c2,l[2]) else 0 + ch |= 0x08 if closer(c1,c2,l[3]) else 0 + + # 0x00 0x01 0x02 0x03 + quad = [ ' ', '▘', '▝', '▀', + # 0x04 0x05 0x06 0x07 + '▖', '▌', '▞', '▛', + # 0x08 0x09 0x0A 0x0B + '▗', '▚', '▐', '▜', + # 0x0C 0x0D 0x0E 0x0F + '▄', '▙', '▟', '█'] + + return TTkString() + \ + (TTkColor.bg(f'#{c1[0]:02X}{c1[1]:02X}{c1[2]:02X}') + \ + TTkColor.fg(f'#{c2[0]:02X}{c2[1]:02X}{c2[2]:02X}')) + \ + quad[ch] + + if deltaR >= deltaG and deltaR >= deltaB: + # Use Red as splitter + return splitReduce(0) + elif deltaG >= deltaB and deltaG >= deltaR: + # Use Green as splitter + return splitReduce(1) + else: + # Use Blue as splitter + return splitReduce(2) + + def paintEvent(self): + img = self._data + for y in range(0, len(img)&(~1), 2): + for x in range(0, min(len(img[y])&(~1),len(img[y+1])&(~1)), 2): + self._canvas.drawText( \ + pos=(x//2,y//2), \ + text=self._reduce( + img[y][x] , img[y][x+1] , + img[y+1][x] , img[y+1][x+1] )) diff --git a/TermTk/TTkWidgets/window.py b/TermTk/TTkWidgets/window.py index 99a7e98e..dac955a6 100644 --- a/TermTk/TTkWidgets/window.py +++ b/TermTk/TTkWidgets/window.py @@ -35,13 +35,20 @@ class TTkWindow(TTkResizableFrame): def __init__(self, *args, **kwargs): TTkResizableFrame.__init__(self, *args, **kwargs) self._name = kwargs.get('name' , 'TTkWindow' ) - self._title = kwargs.get('title' , 0 ) + self._title = kwargs.get('title' , '' ) self.setPadding(3,1,1,1) self._mouseDelta = (0,0) self.setFocusPolicy(TTkK.ClickFocus) self._draggable = False self._menubarTopPosition = 2 + def setTitle(self, title): + self._title = title + self.update() + + def getTitle(self): + return self._title + def paintEvent(self): if self.hasFocus(): color = TTkCfg.theme.windowBorderColorFocus diff --git a/demo/demo.py b/demo/demo.py index 90219ae6..f977de55 100755 --- a/demo/demo.py +++ b/demo/demo.py @@ -25,6 +25,7 @@ import sys, os, argparse import random +sys.path.append(os.path.join(sys.path[0],'../tmp')) sys.path.append(os.path.join(sys.path[0],'..')) import TermTk as ttk diff --git a/demo/showcase/windows.py b/demo/showcase/windows.py index b2116e67..78bc33b7 100755 --- a/demo/showcase/windows.py +++ b/demo/showcase/windows.py @@ -24,6 +24,7 @@ import sys, os +sys.path.append(os.path.join(sys.path[0],'../../tmp')) sys.path.append(os.path.join(sys.path[0],'../..')) import TermTk as ttk @@ -38,6 +39,9 @@ def demoWindows(root=None): win2_2 = ttk.TTkWindow(parent=frame,pos = (5,5), size=(40,20), title="Test Window 2.2", border=True) win2_2.setLayout(ttk.TTkHBoxLayout()) ttk.TTkTestWidget(parent=win2_2, border=False) + + ttk.TTkAbout(parent=frame, pos=(7,7)) + return frame diff --git a/tests/test.ui.016.about.py b/tests/test.ui.016.about.py new file mode 100755 index 00000000..8e1f6934 --- /dev/null +++ b/tests/test.ui.016.about.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 + +# MIT License +# +# Copyright (c) 2021 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. + +import sys, os + +sys.path.append(os.path.join(sys.path[0],'..')) +import TermTk as ttk + +ttk.TTkLog.use_default_file_logging() + +root = ttk.TTk() + +win = ttk.TTkAbout(parent=root, pos=(1,1)) + +root.mainloop() \ No newline at end of file diff --git a/tests/test.ui.016.raster.py b/tests/test.ui.016.raster.py new file mode 100755 index 00000000..1fad3d78 --- /dev/null +++ b/tests/test.ui.016.raster.py @@ -0,0 +1,162 @@ +#!/usr/bin/env python3 + +# MIT License +# +# Copyright (c) 2021 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. + +import sys, os + +sys.path.append(os.path.join(sys.path[0],'..')) +import TermTk as ttk + +ttk.TTkLog.use_default_file_logging() + +from TermTk import TTkWidget, TTkColor, TTkString + +class TTkPeppered(TTkWidget): + # to save space I just recycle the 20x20 imageArray (~10K) + # used in the "TtkAbout" Widget + peppered_20= ttk.TTkAbout.peppered + peppered_10=[ + [[0x00,0x00,0x00], [0x00,0x00,0x00], [0x00,0x00,0x00], [0x00,0x67,0x01], [0x25,0x93,0x1c], [0x22,0x7e,0x12], [0x00,0x00,0x00], [0x00,0x00,0x00], [0x00,0x00,0x00], [0x00,0x00,0x00]], + [[0x00,0x00,0x00], [0x00,0x00,0x00], [0x0a,0x00,0x00], [0x3e,0x29,0x08], [0x2f,0x97,0x2d], [0x2e,0x9a,0x2b], [0x6b,0x3b,0x10], [0x92,0x15,0x16], [0x4b,0x00,0x00], [0x00,0x00,0x00]], + [[0x00,0x00,0x00], [0xcd,0x1e,0x1e], [0xff,0x82,0x82], [0xec,0x0a,0x0c], [0xfb,0x80,0x61], [0x61,0x9f,0x33], [0xea,0x4e,0x42], [0xff,0x70,0x71], [0x81,0x00,0x00], [0x00,0x00,0x00]], + [[0x00,0x00,0x00], [0xa7,0x00,0x00], [0xdd,0x00,0x00], [0xc7,0x00,0x00], [0xff,0x12,0x0e], [0xff,0x2f,0x1d], [0xf1,0x00,0x00], [0x6b,0x00,0x00], [0x00,0x00,0x00], [0x00,0x00,0x00]], + [[0x00,0x00,0x00], [0x00,0x00,0x00], [0x3e,0x00,0x00], [0x65,0x00,0x00], [0xb8,0x00,0x00], [0xdc,0x00,0x00], [0x97,0x00,0x00], [0x86,0x00,0x00], [0x00,0x00,0x00], [0x00,0x00,0x00]], + [[0x00,0x00,0x00], [0x00,0x00,0x00], [0x3f,0x00,0x00], [0xd4,0x00,0x00], [0xc0,0x00,0x00], [0xff,0x00,0x00], [0xea,0x00,0x00], [0xd9,0x00,0x00], [0x22,0x00,0x00], [0x00,0x00,0x00]], + [[0x00,0x00,0x00], [0x00,0x00,0x00], [0x15,0x00,0x00], [0xd7,0x00,0x00], [0xff,0x05,0x06], [0xff,0x09,0x09], [0xff,0x0a,0x0a], [0xe0,0x00,0x00], [0x1e,0x00,0x00], [0x00,0x00,0x00]], + [[0x00,0x00,0x00], [0x00,0x00,0x00], [0x00,0x00,0x00], [0xa2,0x00,0x00], [0xff,0x00,0x00], [0xff,0x69,0x69], [0xff,0x00,0x00], [0xbc,0x00,0x00], [0x14,0x00,0x00], [0x00,0x00,0x00]], + [[0x00,0x00,0x00], [0x00,0x00,0x00], [0x00,0x00,0x00], [0x58,0x00,0x00], [0xb0,0x00,0x00], [0xff,0x72,0x71], [0xe0,0x05,0x05], [0x7c,0x00,0x00], [0x00,0x00,0x00], [0x00,0x00,0x00]], + [[0x00,0x00,0x00], [0x00,0x00,0x00], [0x00,0x00,0x00], [0x00,0x00,0x00], [0x15,0x00,0x00], [0x55,0x00,0x00], [0x21,0x00,0x00], [0x00,0x00,0x00], [0x00,0x00,0x00], [0x00,0x00,0x00]]] + + peppered_old=[ + ['#000000', '#000000', '#000000', '#006701', '#25931c', '#227e12', '#000000', '#000000', '#000000', '#000000'], + ['#000000', '#000000', '#0a0000', '#3e2908', '#2f972d', '#2e9a2b', '#6b3b10', '#921516', '#4b0000', '#000000'], + ['#000000', '#cd1e1e', '#ff8282', '#ec0a0c', '#fb8061', '#619f33', '#ea4e42', '#ff7071', '#810000', '#000000'], + ['#000000', '#a70000', '#dd0000', '#c70000', '#ff120e', '#ff2f1d', '#f10000', '#6b0000', '#000000', '#000000'], + ['#000000', '#000000', '#3e0000', '#650000', '#b80000', '#dc0000', '#970000', '#860000', '#000000', '#000000'], + ['#000000', '#000000', '#3f0000', '#d40000', '#c00000', '#ff0000', '#ea0000', '#d90000', '#220000', '#000000'], + ['#000000', '#000000', '#150000', '#d70000', '#ff0506', '#ff0909', '#ff0a0a', '#e00000', '#1e0000', '#000000'], + ['#000000', '#000000', '#000000', '#a20000', '#ff0000', '#ff6969', '#ff0000', '#bc0000', '#140000', '#000000'], + ['#000000', '#000000', '#000000', '#580000', '#b00000', '#ff7271', '#e00505', '#7c0000', '#000000', '#000000'], + ['#000000', '#000000', '#000000', '#000000', '#150000', '#550000', '#210000', '#000000', '#000000', '#000000']] + def __init__(self, *args, **kwargs): + TTkWidget.__init__(self, *args, **kwargs) + self._name = kwargs.get('name' , 'TTkPeppered' ) + self.setGeometry(0,0,40,40) + + def reduce(self, a,b,c,d): + # quadblitter notcurses like + l = (a,b,c,d) + def delta(i): + return max([v[i] for v in l]) - min([v[i] for v in l]) + deltaR = delta(0) + deltaG = delta(1) + deltaB = delta(2) + + def midColor(c1,c2): + return ((c1[0]+c2[0])//2,(c1[1]+c2[1])//2,(c1[2]+c2[2])//2) + + def closer(a,b,c): + return \ + ( (a[0]-c[0])**2 + (a[1]-c[1])**2 + (a[2]-c[2])**2 ) > \ + ( (b[0]-c[0])**2 + (b[1]-c[1])**2 + (b[2]-c[2])**2 ) + + def splitReduce(i): + s = sorted(l,key=lambda x:x[i]) + mid = (s[3][i]+s[0][i])//2 + if s[1][i] < mid: + if s[2][i] > mid: + c1 = midColor(s[0],s[1]) + c2 = midColor(s[2],s[3]) + else: + c1 = midColor(s[0],s[1]) + c1 = midColor(c1,s[2]) + c2 = s[3] + else: + c1 = s[0] + c2 = midColor(s[1],s[2]) + c2 = midColor(c1,s[3]) + + + ch = 0x01 if closer(c1,c2,l[0]) else 0 + ch |= 0x02 if closer(c1,c2,l[1]) else 0 + ch |= 0x04 if closer(c1,c2,l[2]) else 0 + ch |= 0x08 if closer(c1,c2,l[3]) else 0 + + # 0x00 0x01 0x02 0x03 + quad = [ ' ', '▘', '▝', '▀', + # 0x04 0x05 0x06 0x07 + '▖', '▌', '▞', '▛', + # 0x08 0x09 0x0A 0x0B + '▗', '▚', '▐', '▜', + # 0x0C 0x0D 0x0E 0x0F + '▄', '▙', '▟', '█'] + + return TTkString() + \ + (TTkColor.bg(f'#{c1[0]:02X}{c1[1]:02X}{c1[2]:02X}') + \ + TTkColor.fg(f'#{c2[0]:02X}{c2[1]:02X}{c2[2]:02X}')) + \ + quad[ch] + + if deltaR >= deltaG and deltaR >= deltaB: + # Use Red as splitter + return splitReduce(0) + elif deltaG >= deltaB and deltaG >= deltaR: + # Use Green as splitter + return splitReduce(1) + else: + # Use Blue as splitter + return splitReduce(2) + + def paintEvent(self): + for y, row in enumerate(TTkPeppered.peppered_old): + for x, col in enumerate(row): + if col == "#000000": + color=TTkColor.RST + else: + color=TTkColor.bg(col) + self._canvas.drawText(pos=(x,y), text=' ', color=color) + img = self.peppered_20 + for y in range(0, len(img)&(~1), 2): + for x in range(0, min(len(img[y])&(~1),len(img[y+1])&(~1)), 2): + self._canvas.drawText( \ + pos=(x//2+11,y//2), \ + text=self.reduce( + img[y][x] , img[y][x+1] , + img[y+1][x] , img[y+1][x+1] )) + img = self.peppered_10 + for y in range(0, len(img)&(~1), 2): + for x in range(0, min(len(img[y])&(~1),len(img[y+1])&(~1)), 2): + self._canvas.drawText( \ + pos=(x//2+22,y//2), \ + text=self.reduce( + img[y][x] , img[y][x+1] , + img[y+1][x] , img[y+1][x+1] )) + + self._canvas.drawText(pos=(22,6), text='TEST Peppered') + + +root = ttk.TTk() + +win = ttk.TTkWindow(parent=root,pos = (1,1), size=(40,15), title="About", border=True) +TTkPeppered(parent=win) + +root.mainloop() \ No newline at end of file