kopia lustrzana https://github.com/peterhinch/micropython-micro-gui
Improve greying out of scale classes.
rodzic
4aeaee5312
commit
8001e16aa0
40
README.md
40
README.md
|
@ -1798,4 +1798,42 @@ variable.
|
||||||
|
|
||||||
## 23.2 Use of graphics primitives
|
## 23.2 Use of graphics primitives
|
||||||
|
|
||||||
(ssd and display objects)
|
These notes are for those wishing to draw directly to the `Screen` instance.
|
||||||
|
This is done by providing the user `Screen` class with an `after_open()` method
|
||||||
|
which issues the display driver calls.
|
||||||
|
|
||||||
|
The following code instantiates two classes:
|
||||||
|
```python
|
||||||
|
from hardware_setup import display, ssd
|
||||||
|
```
|
||||||
|
The `ssd` object is an instance of the object defined in the display driver. It
|
||||||
|
is a requirement that this is a subclass of `framebuf.FrameBuffer`. Hence `ssd`
|
||||||
|
supports all the graphics primitives provided by `FrameBuffer`. These may be
|
||||||
|
used to draw on the `Screen`.
|
||||||
|
|
||||||
|
The `display` object has an `ssd` bound variable which is a reference to the
|
||||||
|
`ssd` device. The `display` has methods with the same names and args as those
|
||||||
|
of `ssd`. These support greying out. So you can write (for example)
|
||||||
|
```python
|
||||||
|
display.rect(10, 10, 50, 50, RED)
|
||||||
|
```
|
||||||
|
To render in the correct colors it is wise ensure that greying out is disabled
|
||||||
|
prior to calling `display` methods. This is done with
|
||||||
|
```python
|
||||||
|
display.usegrey(False)
|
||||||
|
```
|
||||||
|
There is little point in issuing `display.rect` as it confers no advantage over
|
||||||
|
`ssd.rect`. However the `Display` class adds methods not currently available in
|
||||||
|
`framebuf`. These are listed below.
|
||||||
|
|
||||||
|
* `circle(self, x0, y0, r, color, width =1)` Width specifies the line width.
|
||||||
|
* `fillcircle(self, x0, y0, r, color)`
|
||||||
|
* `clip_rect(self, x, y, w, h, color)` Rectangle with clipped corners.
|
||||||
|
* `fill_clip_rect(self, x, y, w, h, color)`
|
||||||
|
* `print_left(self, writer, x, y, txt, fgcolor=None, bgcolor=None, invert=False)`
|
||||||
|
* `print_centred(self, writer, x, y, text, fgcolor=None, bgcolor=None, invert=False)`
|
||||||
|
|
||||||
|
Hopefully these are self explanatory. The `Display` methods use the `framebuf`
|
||||||
|
convention of `x, y` coordinates rather than the `row, col` system used by
|
||||||
|
micro-gui.
|
||||||
|
|
||||||
|
|
|
@ -65,15 +65,19 @@ class Display:
|
||||||
self._down.close_func(self.do_down)
|
self._down.close_func(self.do_down)
|
||||||
self._is_grey = False # Not greyed-out
|
self._is_grey = False # Not greyed-out
|
||||||
|
|
||||||
def print_centred(self, writer, x, y, text, fgcolor=None, bgcolor=None):
|
def print_centred(self, writer, x, y, text, fgcolor=None, bgcolor=None, invert=False):
|
||||||
sl = writer.stringlen(text)
|
sl = writer.stringlen(text)
|
||||||
writer.set_textpos(ssd, y - writer.height // 2, x - sl // 2)
|
writer.set_textpos(ssd, y - writer.height // 2, x - sl // 2)
|
||||||
|
if self._is_grey:
|
||||||
|
fgcolor = GREY
|
||||||
writer.setcolor(fgcolor, bgcolor)
|
writer.setcolor(fgcolor, bgcolor)
|
||||||
writer.printstring(text)
|
writer.printstring(text, invert)
|
||||||
writer.setcolor() # Restore defaults
|
writer.setcolor() # Restore defaults
|
||||||
|
|
||||||
def print_left(self, writer, x, y, txt, fgcolor=None, bgcolor=None, invert=False):
|
def print_left(self, writer, x, y, txt, fgcolor=None, bgcolor=None, invert=False):
|
||||||
writer.set_textpos(ssd, y, x)
|
writer.set_textpos(ssd, y, x)
|
||||||
|
if self._is_grey:
|
||||||
|
fgcolor = GREY
|
||||||
writer.setcolor(fgcolor, bgcolor)
|
writer.setcolor(fgcolor, bgcolor)
|
||||||
writer.printstring(txt, invert)
|
writer.printstring(txt, invert)
|
||||||
writer.setcolor() # Restore defaults
|
writer.setcolor() # Restore defaults
|
||||||
|
@ -230,7 +234,6 @@ class Screen:
|
||||||
def show(cls, force):
|
def show(cls, force):
|
||||||
for obj in cls.current_screen.displaylist:
|
for obj in cls.current_screen.displaylist:
|
||||||
if obj.visible: # In a buttonlist only show visible button
|
if obj.visible: # In a buttonlist only show visible button
|
||||||
# pend signals an obect with changed contents
|
|
||||||
if force or obj.draw:
|
if force or obj.draw:
|
||||||
obj.draw_border()
|
obj.draw_border()
|
||||||
obj.show()
|
obj.show()
|
||||||
|
|
|
@ -48,7 +48,7 @@ class CartesianScreen(Screen):
|
||||||
self.g = CartesianGraph(wri, 2, 2, yorigin = 2, fgcolor=GREEN,
|
self.g = CartesianGraph(wri, 2, 2, yorigin = 2, fgcolor=GREEN,
|
||||||
gridcolor=LIGHTGREEN) # Asymmetric y axis
|
gridcolor=LIGHTGREEN) # Asymmetric y axis
|
||||||
Label(wri, 100, 2, 'Asymmetric axes.')
|
Label(wri, 100, 2, 'Asymmetric axes.')
|
||||||
fwdbutton(wri, 2, 130, EmptyScreen, 'Forward', GREEN)
|
fwdbutton(wri, 30, 130, EmptyScreen, 'Forward', GREEN)
|
||||||
CloseButton(wri)
|
CloseButton(wri)
|
||||||
# At this point in time the Screen and graph have been constructed but
|
# At this point in time the Screen and graph have been constructed but
|
||||||
# not rendered. If we drew the curves now they would be overwritten by
|
# not rendered. If we drew the curves now they would be overwritten by
|
||||||
|
@ -76,7 +76,7 @@ class PolarScreen(Screen):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.g = PolarGraph(wri, 2, 2, fgcolor=GREEN, gridcolor=LIGHTGREEN)
|
self.g = PolarGraph(wri, 2, 2, fgcolor=GREEN, gridcolor=LIGHTGREEN)
|
||||||
fwdbutton(wri, 2, 130, EmptyScreen, 'Forward', GREEN)
|
fwdbutton(wri, 30, 130, EmptyScreen, 'Forward', GREEN)
|
||||||
CloseButton(wri)
|
CloseButton(wri)
|
||||||
|
|
||||||
def after_open(self): # After graph has been drawn
|
def after_open(self): # After graph has been drawn
|
||||||
|
@ -94,7 +94,7 @@ class Lissajous(Screen):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.g = CartesianGraph(wri, 2, 2, fgcolor=GREEN, gridcolor=LIGHTGREEN)
|
self.g = CartesianGraph(wri, 2, 2, fgcolor=GREEN, gridcolor=LIGHTGREEN)
|
||||||
Label(wri, 100, 2, 'Lissajous figure.')
|
Label(wri, 100, 2, 'Lissajous figure.')
|
||||||
fwdbutton(wri, 2, 130, EmptyScreen, 'Forward', GREEN)
|
fwdbutton(wri, 30, 130, EmptyScreen, 'Forward', GREEN)
|
||||||
CloseButton(wri)
|
CloseButton(wri)
|
||||||
|
|
||||||
def after_open(self): # After graph has been drawn
|
def after_open(self): # After graph has been drawn
|
||||||
|
@ -111,7 +111,7 @@ class Lemniscate(Screen):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.g = CartesianGraph(wri, 2, 2, height = 75, fgcolor=GREEN, gridcolor=LIGHTGREEN)
|
self.g = CartesianGraph(wri, 2, 2, height = 75, fgcolor=GREEN, gridcolor=LIGHTGREEN)
|
||||||
Label(wri, 82, 2, 'To infinity and beyond...')
|
Label(wri, 82, 2, 'To infinity and beyond...')
|
||||||
fwdbutton(wri, 2, 130, EmptyScreen, 'Forward', GREEN)
|
fwdbutton(wri, 30, 130, EmptyScreen, 'Forward', GREEN)
|
||||||
CloseButton(wri)
|
CloseButton(wri)
|
||||||
|
|
||||||
def after_open(self): # After graph has been drawn
|
def after_open(self): # After graph has been drawn
|
||||||
|
@ -130,7 +130,7 @@ class PolarClip(Screen):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.g = PolarGraph(wri, 2, 2, fgcolor=GREEN, gridcolor=LIGHTGREEN)
|
self.g = PolarGraph(wri, 2, 2, fgcolor=GREEN, gridcolor=LIGHTGREEN)
|
||||||
Label(wri, 100, 2, 'Clipping of polar data.')
|
Label(wri, 100, 2, 'Clipping of polar data.')
|
||||||
fwdbutton(wri, 2, 130, EmptyScreen, 'Forward', GREEN)
|
fwdbutton(wri, 30, 130, EmptyScreen, 'Forward', GREEN)
|
||||||
CloseButton(wri)
|
CloseButton(wri)
|
||||||
|
|
||||||
def after_open(self): # After graph has been drawn
|
def after_open(self): # After graph has been drawn
|
||||||
|
@ -148,7 +148,7 @@ class RTPolar(Screen):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.g = PolarGraph(wri, 2, 2, fgcolor=GREEN, gridcolor=LIGHTGREEN)
|
self.g = PolarGraph(wri, 2, 2, fgcolor=GREEN, gridcolor=LIGHTGREEN)
|
||||||
Label(wri, 100, 2, 'Realtime polar data.')
|
Label(wri, 100, 2, 'Realtime polar data.')
|
||||||
fwdbutton(wri, 2, 130, EmptyScreen, 'Forward', GREEN)
|
fwdbutton(wri, 30, 130, EmptyScreen, 'Forward', GREEN)
|
||||||
CloseButton(wri)
|
CloseButton(wri)
|
||||||
|
|
||||||
def after_open(self): # After graph has been drawn
|
def after_open(self): # After graph has been drawn
|
||||||
|
@ -168,7 +168,7 @@ class RTRect(Screen):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.g = CartesianGraph(wri, 2, 2, fgcolor=GREEN, gridcolor=LIGHTGREEN)
|
self.g = CartesianGraph(wri, 2, 2, fgcolor=GREEN, gridcolor=LIGHTGREEN)
|
||||||
Label(wri, 100, 2, 'Realtime discontinuous data.')
|
Label(wri, 100, 2, 'Realtime discontinuous data.')
|
||||||
fwdbutton(wri, 2, 130, EmptyScreen, 'Forward', GREEN)
|
fwdbutton(wri, 30, 130, EmptyScreen, 'Forward', GREEN)
|
||||||
CloseButton(wri)
|
CloseButton(wri)
|
||||||
|
|
||||||
def after_open(self): # After graph has been drawn
|
def after_open(self): # After graph has been drawn
|
||||||
|
@ -198,7 +198,7 @@ class TSeq(Screen):
|
||||||
self.g = CartesianGraph(wri, 2, 2, xorigin = 10, fgcolor=GREEN,
|
self.g = CartesianGraph(wri, 2, 2, xorigin = 10, fgcolor=GREEN,
|
||||||
gridcolor=LIGHTGREEN, bdcolor=False)
|
gridcolor=LIGHTGREEN, bdcolor=False)
|
||||||
Label(wri, 100, 2, 'Time sequence.')
|
Label(wri, 100, 2, 'Time sequence.')
|
||||||
fwdbutton(wri, 2, 130, EmptyScreen, 'Forward', GREEN)
|
fwdbutton(wri, 30, 130, EmptyScreen, 'Forward', GREEN)
|
||||||
CloseButton(wri)
|
CloseButton(wri)
|
||||||
|
|
||||||
def after_open(self): # After graph has been drawn
|
def after_open(self): # After graph has been drawn
|
||||||
|
@ -241,8 +241,8 @@ class BaseScreen(Screen):
|
||||||
Screen.change(d[lb.textvalue()])
|
Screen.change(d[lb.textvalue()])
|
||||||
|
|
||||||
def test():
|
def test():
|
||||||
if display.height < 240 or display.width < 320:
|
if display.height < 128 or display.width < 200:
|
||||||
print(' This test requires a display of at least 320x240 pixels.')
|
print(' This test requires a display of at least 128x200 pixels.')
|
||||||
else:
|
else:
|
||||||
print('Testing micro-gui...')
|
print('Testing micro-gui...')
|
||||||
Screen.change(BaseScreen)
|
Screen.change(BaseScreen)
|
||||||
|
|
|
@ -53,15 +53,18 @@ class FooScreen(Screen):
|
||||||
self.rb0 = None
|
self.rb0 = None
|
||||||
self.bs0 = None
|
self.bs0 = None
|
||||||
wri = CWriter(ssd, arial10, GREEN, BLACK, verbose=False)
|
wri = CWriter(ssd, arial10, GREEN, BLACK, verbose=False)
|
||||||
lbltim = Label(wri, 50, 85, 'this is a test', bdcolor=RED)
|
lbltim = Label(wri, 65, 100, 'this is a test', bdcolor=RED)
|
||||||
|
|
||||||
m0 = Meter(wri, 20, 240, divisions = 4, ptcolor=YELLOW,
|
m0 = Meter(wri, 10, 240, divisions = 4, ptcolor=YELLOW, height=80, width=15,
|
||||||
label='left', style=Meter.LINE, legends=('0.0', '0.5', '1.0'))
|
label='Meter example', style=Meter.BAR, legends=('0.0', '0.5', '1.0'))
|
||||||
# Instantiate displayable objects. bgcolor forces complete redraw.
|
# Instantiate displayable objects. bgcolor forces complete redraw.
|
||||||
dial = Dial(wri, 2, 2, height = 75, ticks = 12, bgcolor=BLACK, bdcolor=None, label=120) # Border in fg color
|
dial = Dial(wri, 2, 2, height = 75, ticks = 12, bgcolor=BLACK, bdcolor=None, label=120) # Border in fg color
|
||||||
scale = Scale(wri, 2, 100, width = 124, tickcb = tickcb,
|
scale = Scale(wri, 2, 100, width = 124, tickcb = tickcb,
|
||||||
pointercolor=RED, fontcolor=YELLOW, bdcolor=CYAN)
|
pointercolor=RED, fontcolor=YELLOW, bdcolor=CYAN)
|
||||||
|
|
||||||
|
row = 105
|
||||||
|
col = 2
|
||||||
|
Label(wri, row, col, 'Normal buttons')
|
||||||
# Four Button instances
|
# Four Button instances
|
||||||
row = 120
|
row = 120
|
||||||
ht = 30
|
ht = 30
|
||||||
|
@ -73,8 +76,9 @@ class FooScreen(Screen):
|
||||||
self.bs = ButtonList(self.callback)
|
self.bs = ButtonList(self.callback)
|
||||||
self.bs0 = None
|
self.bs0 = None
|
||||||
col+= 50
|
col+= 50
|
||||||
|
Label(wri, row - 15, col, 'ButtonList')
|
||||||
for t in table_buttonset: # Buttons overlay each other at same location
|
for t in table_buttonset: # Buttons overlay each other at same location
|
||||||
button = self.bs.add_button(wri, 120, col, shape=RECTANGLE, textcolor=BLUE, height=30, **t)
|
button = self.bs.add_button(wri, row, col, shape=RECTANGLE, textcolor=BLUE, height=30, **t)
|
||||||
if self.bs0 is None: # Save for reset button callback
|
if self.bs0 is None: # Save for reset button callback
|
||||||
self.bs0 = button
|
self.bs0 = button
|
||||||
|
|
||||||
|
@ -82,21 +86,25 @@ class FooScreen(Screen):
|
||||||
col+= 60
|
col+= 60
|
||||||
btn = Button(wri, row, col, height=30, callback=self.rstcb, text='reset', litcolor=RED, fgcolor=GREEN, bgcolor=DARKGREEN)
|
btn = Button(wri, row, col, height=30, callback=self.rstcb, text='reset', litcolor=RED, fgcolor=GREEN, bgcolor=DARKGREEN)
|
||||||
|
|
||||||
|
col = 2
|
||||||
|
row = 170
|
||||||
|
Label(wri, row, col, 'Radio buttons')
|
||||||
# Radio buttons
|
# Radio buttons
|
||||||
col= 2
|
row = 185
|
||||||
self.rb = RadioButtons(BLUE, self.rbcb) # color of selected button
|
self.rb = RadioButtons(BLUE, self.rbcb) # color of selected button
|
||||||
self.rb0 = None
|
self.rb0 = None
|
||||||
for t in table_radiobuttons:
|
for t in table_radiobuttons:
|
||||||
button = self.rb.add_button(wri, 160, col, textcolor = WHITE,
|
button = self.rb.add_button(wri, row, col, textcolor = WHITE,
|
||||||
fgcolor = BLUE, bgcolor = DARKBLUE, shape=CIRCLE, height = 30, **t)
|
fgcolor = BLUE, bgcolor = DARKBLUE, shape=CIRCLE, height = 30, **t)
|
||||||
if self.rb0 is None: # Save for reset button callback
|
if self.rb0 is None: # Save for reset button callback
|
||||||
self.rb0 = button
|
self.rb0 = button
|
||||||
col+= 35
|
col+= 35
|
||||||
# Checkbox
|
# Checkbox
|
||||||
col+= 35
|
col+= 35
|
||||||
Checkbox(wri, 160, col, callback=self.cbcb)
|
Label(wri, row - 15, col, 'Checkbox and LED')
|
||||||
|
Checkbox(wri, row, col, callback=self.cbcb)
|
||||||
col+= 40
|
col+= 40
|
||||||
self.led = LED(wri, 160, col, color=YELLOW, bdcolor=GREEN)
|
self.led = LED(wri, row, col, color=YELLOW, bdcolor=GREEN)
|
||||||
CloseButton(wri)
|
CloseButton(wri)
|
||||||
asyncio.create_task(run(dial, lbltim, m0, scale))
|
asyncio.create_task(run(dial, lbltim, m0, scale))
|
||||||
|
|
||||||
|
@ -109,7 +117,7 @@ class FooScreen(Screen):
|
||||||
|
|
||||||
def rstcb(self, button):
|
def rstcb(self, button):
|
||||||
print('Reset button: init ButtonList and RadioButtons')
|
print('Reset button: init ButtonList and RadioButtons')
|
||||||
self.bs.value(self.bs0) # BUG This is calling ButtonList.value which calls ._update -> Screen.select which changes currency
|
self.bs.value(self.bs0)
|
||||||
self.rb.value(self.rb0)
|
self.rb.value(self.rb0)
|
||||||
|
|
||||||
def cbcb(self, cb):
|
def cbcb(self, cb):
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# meter.py Extension to ugui providing a linear "meter" widget.
|
# meter.py Extension to ugui providing a linear "meter" widget.
|
||||||
|
|
||||||
# Released under the MIT License (MIT). See LICENSE.
|
# Released under the MIT License (MIT). See LICENSE.
|
||||||
# Copyright (c) 2019 Peter Hinch
|
# Copyright (c) 2021 Peter Hinch
|
||||||
|
|
||||||
from gui.core.ugui import Widget, display
|
from gui.core.ugui import Widget, display
|
||||||
from gui.widgets.label import Label
|
from gui.widgets.label import Label
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
from gui.core.ugui import LinearIO, display
|
from gui.core.ugui import LinearIO, display
|
||||||
from hardware_setup import ssd # Display driver for Writer
|
from hardware_setup import ssd # Display driver for Writer
|
||||||
from gui.core.writer import Writer
|
from gui.core.writer import Writer
|
||||||
from gui.core.colors import BLACK
|
from gui.core.colors import *
|
||||||
|
|
||||||
dolittle = lambda *_ : None
|
dolittle = lambda *_ : None
|
||||||
|
|
||||||
|
@ -84,6 +84,7 @@ class Scale(LinearIO):
|
||||||
# So pixels per unit value == win_width/200
|
# So pixels per unit value == win_width/200
|
||||||
win_width: int = x1 - x0
|
win_width: int = x1 - x0
|
||||||
ticks: int = self.ticks # Total # of ticks visible and hidden
|
ticks: int = self.ticks # Total # of ticks visible and hidden
|
||||||
|
txtcolor = GREY if self.greyed_out() else self.fontcolor
|
||||||
while True:
|
while True:
|
||||||
x: int = x0 + (fx * win_width) // 200 # Current X position
|
x: int = x0 + (fx * win_width) // 200 # Current X position
|
||||||
ys: int # Start Y position for tick
|
ys: int # Start Y position for tick
|
||||||
|
@ -94,7 +95,7 @@ class Scale(LinearIO):
|
||||||
txt = self.legendcb(self._fvalue(iv * 10))
|
txt = self.legendcb(self._fvalue(iv * 10))
|
||||||
tlen = wri.stringlen(txt)
|
tlen = wri.stringlen(txt)
|
||||||
Writer.set_textpos(ssd, y0, min(x, x1 - tlen))
|
Writer.set_textpos(ssd, y0, min(x, x1 - tlen))
|
||||||
wri.setcolor(self.fontcolor, self.bgcolor)
|
wri.setcolor(txtcolor, self.bgcolor)
|
||||||
wri.printstring(txt)
|
wri.printstring(txt)
|
||||||
wri.setcolor()
|
wri.setcolor()
|
||||||
ys = self.ldy0 # Large tick
|
ys = self.ldy0 # Large tick
|
||||||
|
|
|
@ -15,7 +15,7 @@ from math import log10
|
||||||
from gui.core.ugui import LinearIO, display
|
from gui.core.ugui import LinearIO, display
|
||||||
from hardware_setup import ssd # Display driver for Writer
|
from hardware_setup import ssd # Display driver for Writer
|
||||||
from gui.core.writer import Writer
|
from gui.core.writer import Writer
|
||||||
from gui.core.colors import BLACK
|
from gui.core.colors import *
|
||||||
|
|
||||||
# Null function
|
# Null function
|
||||||
dolittle = lambda *_ : None
|
dolittle = lambda *_ : None
|
||||||
|
@ -86,6 +86,7 @@ class ScaleLog(LinearIO):
|
||||||
vc = self._value # Current value, corresponds to centre of display
|
vc = self._value # Current value, corresponds to centre of display
|
||||||
d = int(log10(vc)) - 1 # 10**d is start of a decade guaranteed to be outside display
|
d = int(log10(vc)) - 1 # 10**d is start of a decade guaranteed to be outside display
|
||||||
vs = max(10 ** d, 1.0) # vs: start value of current decade
|
vs = max(10 ** d, 1.0) # vs: start value of current decade
|
||||||
|
txtcolor = GREY if self.greyed_out() else self.fontcolor
|
||||||
while True: # For each decade until we run out of space
|
while True: # For each decade until we run out of space
|
||||||
done = True # Assume completion
|
done = True # Assume completion
|
||||||
xs: float = xc - dw * log10(vc / vs) # x location of start of scale
|
xs: float = xc - dw * log10(vc / vs) # x location of start of scale
|
||||||
|
@ -102,7 +103,7 @@ class ScaleLog(LinearIO):
|
||||||
txt = self.legendcb(vt)
|
txt = self.legendcb(vt)
|
||||||
tlen = wri.stringlen(txt)
|
tlen = wri.stringlen(txt)
|
||||||
Writer.set_textpos(ssd, y0, min(x, x1 - tlen))
|
Writer.set_textpos(ssd, y0, min(x, x1 - tlen))
|
||||||
wri.setcolor(self.fontcolor, self.bgcolor)
|
wri.setcolor(txtcolor, self.bgcolor)
|
||||||
wri.printstring(txt)
|
wri.printstring(txt)
|
||||||
ys = self.ldy0 # Large tick
|
ys = self.ldy0 # Large tick
|
||||||
yl = self.ldl
|
yl = self.ldl
|
||||||
|
|
Ładowanie…
Reference in New Issue