Browse Source

multiple values in the graph widget, visibility is checked among the parents

pull/4/head
Eugenio Parodi 5 years ago
parent
commit
044130bcea
  1. 67
      TermTk/TTkCore/canvas.py
  2. 5
      TermTk/TTkCore/constant.py
  3. 2
      TermTk/TTkCore/helper.py
  4. 46
      TermTk/TTkGui/theme.py
  5. 28
      TermTk/TTkWidgets/graph.py
  6. 5
      TermTk/TTkWidgets/widget.py
  7. 82
      tests/showcase/graph.py
  8. 52
      tests/utf-8/test.braille.py

67
TermTk/TTkCore/canvas.py

@ -343,14 +343,8 @@ class TTkCanvas:
def drawHChart(self, pos, values, zoom=1.0, color=TTkColor.RST):
x,y=pos
v1,v2 = values
t1,t2,b1,b2=0,0,0,0
gu=TTkCfg.theme.graph_up
gd=TTkCfg.theme.graph_down
if v1>0: t1 = v1*zoom
else: b1 = v1*zoom
if v2>0: t2 = v2*zoom
else: b2 = v2*zoom
gb=TTkCfg.theme.braille
'''
loop 0 1 2 3 = range(0,1+maxt//4)
v1 13 |---|---|---|--|
@ -359,21 +353,48 @@ class TTkCanvas:
out 4,4 4,4 4,2 3,0 0,0
o1 = 4 if v1-4 > i*4 else v1-i*4
'''
# Draw Top Chart
maxt = max(t1,t2)
for i in range(0,int(maxt//4)+1):
o1 = 4 if t1-4 > i*4 else max(0,int(t1-i*4))
o2 = 4 if t2-4 > i*4 else max(0,int(t2-i*4))
#TTkLog.debug(f"{v1,v2},{(t1//4),(t2//4)}, {(t1%4),(t2%4)}, {o1,o2}")
self._set(y-i,x, gu[o1][o2], color)
# Draw Bottom Chart
minb = min(b1,b2)
for i in range(int(minb//4),0):
o1 = 4 if -b1-4 > -i*4 else max(0,int(-b1+i*4))
o2 = 4 if -b2-4 > -i*4 else max(0,int(-b2+i*4))
##TTkLog.debug(f"{v1,v2},{(t1//(t2//4)}, {(t1%4),(t2%4)}, {o1,o2}")
self._set(y-i,x, gd[o1][o2], color)
# TTkLog.debug(f"{(v1,v2)} z{zoom}")
zl1 = [ int(i*zoom) for i in v1 ]
zl2 = [ int(i*zoom) for i in v2 ]
maxz = max(max(zl1),max(zl2),0)
minz = min(min(zl1),min(zl2),0)
filled = True
for i in range(int(minz//4),int(maxz//4)+2):
ts1 = i*4
ts2 = i*4+4
'''
Braille bits:
o2 o1 = 4 bits each
1 5 Braille dots
2 6
3 7
4 8
TTkTheme.braille[( o1<<4 | o2 )] = Braille UTF-8 char
'''
braille = 0x00
for ii in range(len(zl1)):
z1 = zl1[ii]
z2 = zl2[ii]
o1,o2 = 0,0
#TTkLog.debug
if not filled or ii>0:
if ts1 <= z1 < ts2: o1 = 0x80>>max(0,int(z1-ts1))
if ts1 <= z2 < ts2: o2 = 0x08>>max(0,int(z2-ts1))
else:
if (0<=ts1<z1)or(0>ts1>z1): o1 = 0xf0
if (0<=ts1<z2)or(0>ts1>z2): o2 = 0x0f
k1 = 0x0f80 if z1>=0 else 0x00f0
k2 = 0x00f8 if z2>=0 else 0x000f
if ts1 <= z1 < ts2: o1 = 0xf0&(k1>>max(0,int(z1-ts1)))
if ts1 <= z2 < ts2: o2 = 0x0f&(k2>>max(0,int(z2-ts1)))
braille ^= (o1|o2)
# braille &= 0xff
#TTkLog.debug(f"z:{zl1,zl2}, ts:{ts1,ts2},{o1,o2}")
#if braille<0 or braille>0xff:
# TTkLog.debug(f"z:{zl1,zl2},t:{t1,t2},i:{i} {t1-i*4} {t2-i*4} o:{o1,o2}, {hex(braille)}")
self._set(y-i-1,x, gb[braille], color)
def execPaint(self, winw, winh):

5
TermTk/TTkCore/constant.py

@ -41,6 +41,11 @@ class TTkConstant:
BOTTOM = 0x0002
LEFT = 0x0004
RIGHT = 0x0008
CENTER = 0x0010
# Graph types
FILLED = 0x0001
LINE = 0x0002
# Mouse Events
MOUSE_EVENT = 0x01

2
TermTk/TTkCore/helper.py

@ -46,6 +46,7 @@ class TTkHelper:
@staticmethod
def addUpdateWidget(widget):
if not widget.isVisible(): return
if widget not in TTkHelper._updateWidget:
TTkHelper._updateWidget.append(widget)
@ -104,6 +105,7 @@ class TTkHelper:
# TTkLog.debug(f"{len(TTkHelper._updateBuffer)} {len(TTkHelper._updateWidget)}")
for widget in TTkHelper._updateWidget:
if not widget.isVisible(): continue
parent = widget.parentWidget()
while parent is not None:
if parent not in updateBuffers:

46
TermTk/TTkGui/theme.py

@ -24,6 +24,7 @@
from TermTk.TTkCore.color import TTkColor
class TTkTheme():
''' from: https://en.wikipedia.org/wiki/Box-drawing_character
@ -149,19 +150,38 @@ class TTkTheme():
'''
graph_up = (
(' ','','','',''),
('','','','',''),
('','','','',''),
('','','','',''),
('','','','',''))
graph_down=(
(' ','','','',''),
('','','','',''),
('','','','',''),
('','','','',''),
('','','','',''))
# graph_up = (
# (' ','⢀','⢠','⢰','⢸'),
# ('⡀','⣀','⣠','⣰','⣸'),
# ('⡄','⣄','⣤','⣴','⣼'),
# ('⡆','⣆','⣦','⣶','⣾'),
# ('⡇','⣇','⣧','⣷','⣿'))
# graph_down=(
# (' ','⠈','⠘','⠸','⢸'),
# ('⠁','⠉','⠙','⠹','⢹'),
# ('⠃','⠋','⠛','⠻','⢻'),
# ('⠇','⠏','⠟','⠿','⢿'),
# ('⡇','⡏','⡟','⡿','⣿'))
# Generated by:
# tests/utf-8/test.braille.py
braille=(
'','','','','','','','','','','','','','','','',
'','','','','','','','','','','','','','','','',
'','','','','','','','','','','','','','','','',
'','','','','','','','','','','','','','','','',
'','','','','','','','','','','','','','','','',
'','','','','','','','','','','','','','','','',
'','','','','','','','','','','','','','','','',
'','','','','','','','','','','','','','','','',
'','','','','','','','','','','','','','','','',
'','','','','','','','','','','','','','','','',
'','','','','','','','','','','','','','','','',
'','','','','','','','','','','','','','','','',
'','','','','','','','','','','','','','','','',
'','','','','','','','','','','','','','','','',
'','','','','','','','','','','','','','','','',
'','','','','','','','','','','','','','','','')
frameBorderColor = TTkColor.RST
frameTitleColor = TTkColor.fg("#dddddd")+TTkColor.bg("#222222")

28
TermTk/TTkWidgets/graph.py

@ -34,29 +34,37 @@ from TermTk.TTkWidgets.widget import TTkWidget
from TermTk.TTkTemplates.color import TColor
class TTkGraph(TTkWidget, TColor):
__slots__ = ('_data', '_maxData', '_offset', '_direction')
__slots__ = ('_data', '_maxData', '_offset', '_direction', '_align')
def __init__(self, *args, **kwargs):
self._data = []
self._data = [[0]]
self._offset = 0
TTkWidget.__init__(self, *args, **kwargs)
TColor.__init__(self, *args, **kwargs)
self._name = kwargs.get('name' , 'TTkGraph' )
self._maxData = kwargs.get('maxData', 0x1000)
self._direction = kwargs.get('direction', TTkK.RIGHT)
self._align = kwargs.get('align', TTkK.CENTER)
def addValue(self, value):
self._data.append(value)
def addValue(self, values):
self._data.append(values)
self.update()
def paintEvent(self):
if not self._data: return
x=0
y = self.height()//2
w,h = self.size()
v1,v2 = 0,0
x=0
if self._align == TTkK.CENTER:
y = h//2
elif self._align == TTkK.TOP:
y = 0
else:
y = h
v1,v2 = [0],[0]
i=0
data = self._data[-w*2:]
zoom = 2*h/max(max(data),-min(data))
# TTkLog.debug(data)
mv = max(max(map(max,data)),-min(map(min,data)))
zoom = 2*h/mv if mv>0 else 1.0
for i in range(len(data)):
v2 = v1
v1 = data[i]
@ -67,6 +75,6 @@ class TTkGraph(TTkWidget, TColor):
self._canvas.drawHChart(pos=(w-(x+i//2),y),values=(v1,v2), zoom=zoom, color=self.color.modParam(val=-y))
if i%2==1:
if self._direction == TTkK.RIGHT:
self._canvas.drawHChart(pos=(x+i//2+1,y),values=(v1,0), zoom=zoom, color=self.color.modParam(val=-y))
self._canvas.drawHChart(pos=(x+i//2+1,y),values=(v1,v1), zoom=zoom, color=self.color.modParam(val=-y))
else:
self._canvas.drawHChart(pos=(w-(x+i//2+1),y),values=(0,v1), zoom=zoom, color=self.color.modParam(val=-y))
self._canvas.drawHChart(pos=(w-(x+i//2+1),y),values=(v1,v1), zoom=zoom, color=self.color.modParam(val=-y))

5
TermTk/TTkWidgets/widget.py

@ -420,7 +420,10 @@ class TTkWidget:
def close(self): pass
def isVisible(self):
return self._visible
if self._parent is None:
return self._visible
else:
return self._visible & self._parent.isVisible()
# Event to be sent
# TODO: Remove This

82
tests/showcase/graph.py

@ -27,48 +27,66 @@ import sys, os, argparse, math, random
sys.path.append(os.path.join(sys.path[0],'../..'))
import TermTk as ttk
class graphTimerEvent():
def __init__(self, w, type, delay):
self.timer = ttk.TTkTimer()
self.val = 10
self.delay = delay
self.switch = False
self.w = w
self.type = type
self.timer.timeout.connect(self.timerEvent)
self.timer.start(1)
@ttk.pyTTkSlot()
def timerEvent(self):
self.switch = not self.switch
if self.type == 1: # Triple sin
offset1 = 15
offset2 = 20
val = [ math.sin( self.val *math.pi/40)*4*10 ,
math.sin((self.val+offset1)*math.pi/40)*4*7,
math.sin((self.val+offset2)*math.pi/30)*4*5,]
if self.type == 2: # Double sin alternated
offset = 15
if self.switch: val = [math.sin( self.val *math.pi/40)*4*10]
else: val = [math.sin((self.val+offset)*math.pi/40)*4*7 ]
if self.type == 3: # random + sin
val = [ random.uniform(15,+40),
math.sin((self.val)*math.pi/30)*15+20,
]
if self.type == 5: # random
val = [random.uniform(-40,-10)]
if self.type == 6: # random
val = [random.uniform(-40,+40)]
if self.type == 4: # mix rand and sin
if self.switch: val = [math.sin(self.val*math.pi/40)*4*10]
else: val = [random.uniform(-40,+40)]
self.val+=1
self.w.addValue(val)
self.timer.start(self.delay)
def demoGraph(root= None):
frame = ttk.TTkFrame(parent=root, border=False, layout=ttk.TTkGridLayout())
graphWidget1 = ttk.TTkGraph(color=ttk.TTkColor.fg('#00dddd', modifier=ttk.TTkColorGradient(increment=-25)))
graphWidget2 = ttk.TTkGraph(direction=ttk.TTkK.LEFT, color=ttk.TTkColor.fg('#ff8800', modifier=ttk.TTkColorGradient(increment= 40)))
graphWidget3 = ttk.TTkGraph(color=ttk.TTkColor.fg('#dd00dd', modifier=ttk.TTkColorGradient(increment=-20)))
graphWidget3 = ttk.TTkGraph(align=ttk.TTkK.BOTTOM, color=ttk.TTkColor.fg('#dd00dd', modifier=ttk.TTkColorGradient(increment=-20)))
graphWidget4 = ttk.TTkGraph(color=ttk.TTkColor.fg('#00dd44', modifier=ttk.TTkColorGradient(increment=-30)))
graphWidget5 = ttk.TTkGraph(align=ttk.TTkK.TOP, color=ttk.TTkColor.fg('#dd44dd', modifier=ttk.TTkColorGradient(increment=-20)))
graphWidget6 = ttk.TTkGraph(color=ttk.TTkColor.fg('#00dd44', modifier=ttk.TTkColorGradient(increment=-30)))
frame.layout().addWidget(graphWidget1, 0,0)
frame.layout().addWidget(graphWidget2, 0,1)
frame.layout().addWidget(graphWidget3, 1,0)
frame.layout().addWidget(graphWidget4, 1,1)
class timerEvent():
def __init__(self, w, type):
self.timer = ttk.TTkTimer()
self.val = 10
self.switch = False
self.w = w
self.type = type
self.timer.timeout.connect(self.timerEvent)
self.timer.start(1)
@ttk.pyTTkSlot()
def timerEvent(self):
self.switch = not self.switch
if self.type == 1: # Simple sin
val = math.sin(self.val*math.pi/40)*4*10
if self.type == 2: # Double sin
offset = 15
if self.switch: val = math.sin(self.val*math.pi/40)*4*10
else: val = math.sin((self.val+offset)*math.pi/40)*4*7
if self.type == 3: # random
val = random.uniform(-40,+40)
if self.type == 4: # mix rand and sin
if self.switch: val = math.sin(self.val*math.pi/40)*4*10
else: val = random.uniform(-40,+40)
self.val+=1
self.w.addValue(val)
self.timer.start(0.1)
timerEvent(graphWidget1, 1)
timerEvent(graphWidget2, 2)
timerEvent(graphWidget3, 3)
timerEvent(graphWidget4, 4)
frame.layout().addWidget(graphWidget5, 2,0)
frame.layout().addWidget(graphWidget6, 2,1)
graphTimerEvent(graphWidget1, 1, 0.1)
graphTimerEvent(graphWidget2, 2, 0.1)
graphTimerEvent(graphWidget3, 3, 0.1)
graphTimerEvent(graphWidget4, 4, 0.05)
graphTimerEvent(graphWidget5, 5, 0.1)
graphTimerEvent(graphWidget6, 6, 0.1)
return frame
def main():
parser = argparse.ArgumentParser()
parser.add_argument('-f', help='Full Screen', action='store_true')

52
tests/utf-8/test.braille.py

@ -0,0 +1,52 @@
#!/usr/bin/env python3
# MIT License
#
# Copyright (c) 2021 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.
'''
bits utf-8 diff with utf8 bits
0 4 0,1,2 -> 0x00->0x07 ch012
1 5 4,5,6 -> 0x00->0x07 << 3 ch456>>1
2 6
3 7
| \---> 7 -> 0x80 ch7
\-----> 3 -> 0x40 ch3<<3
'''
def ch2braille(ch):
ch012 = ch & 0x07
ch456 = ch & 0x70
ch3 = ch & 0x08
ch7 = ch & 0x80
return 0x2800 | ch012 | (ch456>>1) | (ch3<<3) | ch7
codes = [ chr(ch2braille(ch)) for ch in range(0,0x100)]
print("braille=(")
for a in range(0x10):
for b in range(0x10):
val = a | (b<<4)
print(f"'{codes[val]}',",end='')
print()
print(")")
Loading…
Cancel
Save