Ankerseite: Werte über Tastatur änderbar
This commit is contained in:
parent
986d222a98
commit
dafcfaca6b
108
cfgmenu.py
108
cfgmenu.py
|
@ -5,44 +5,94 @@ Menüsystem für Konfiguration(en)
|
||||||
|
|
||||||
class MenuItem():
|
class MenuItem():
|
||||||
|
|
||||||
def __init__(self, itmname):
|
def __init__(self, valtype, label, value=None, unit=''):
|
||||||
self.name = itmname
|
validtypes = ('int', 'bool')
|
||||||
self.label = None
|
valtype = valtype.lower() # Groß- und Kleinschreibung lassen wir gemischt zu
|
||||||
self.value = None
|
if valtype not in validtypes:
|
||||||
self.steps = (1,)
|
raise TypeError(f"Invalid value type: '{valtype}'. Only supported: {validtypes}")
|
||||||
|
self.label = label # Anzeigetext des Menüeintrag
|
||||||
|
self.value = value # Zugeordneter Wert für diesen Eintrag
|
||||||
|
self.unit = unit
|
||||||
|
self._type = valtype
|
||||||
|
self._min = 0
|
||||||
|
self._max = 99999
|
||||||
|
self.steps = (1, 10, 100, 1000) # Sprungmöglichkeiten für +/- Tasten
|
||||||
|
self.step = 0 # index into tuple above
|
||||||
|
self.position = None # Menüposition gezählt von 0 an
|
||||||
|
|
||||||
|
def setRange(self, valmin, valmax, steps):
|
||||||
|
self.min = valmin
|
||||||
|
self.max = valmax
|
||||||
|
self.steps = steps
|
||||||
|
|
||||||
def setValue(self, val):
|
def setValue(self, val):
|
||||||
self.value = val
|
if self._type == 'int':
|
||||||
|
if val >= self._min and val <= self._max:
|
||||||
|
self.value = val
|
||||||
|
return True
|
||||||
|
elif self.type == 'bool':
|
||||||
|
self.value = val
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
class Menu():
|
class Menu():
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, title, x, y):
|
||||||
title = None
|
self.title = title
|
||||||
x = 0
|
self.items = {} # Items über Schlüssel zugreifbar
|
||||||
y = 0
|
self.activeitem = -1 # Noch nichts aktiv
|
||||||
w = 100
|
self._x = x
|
||||||
h = 20
|
self._y = y
|
||||||
items = []
|
self._w = 100
|
||||||
itm_active = -1 # nothing activated
|
self._h = 20
|
||||||
self._index = -1
|
self._index = [] # Mapping zwischen Index(Position) und Schlüssel
|
||||||
|
self._iter_index = 0
|
||||||
def addItem(self, label):
|
|
||||||
itm = MenuItem(label)
|
|
||||||
items.append(itm)
|
|
||||||
|
|
||||||
class MenuIter():
|
|
||||||
|
|
||||||
def __init__(self, menu):
|
|
||||||
self._items = menu.items
|
|
||||||
self._class_size = len(self._items)
|
|
||||||
self._index = 0
|
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def __next__(self):
|
def __next__(self):
|
||||||
if self._index < self._class_size:
|
if self._iter_index < len(self.items):
|
||||||
itm = items[self._index]
|
itm = self.items[self._index[self._iter_index]]
|
||||||
self._index += 1
|
self._iter_index += 1
|
||||||
return itm
|
return itm
|
||||||
|
self._iter_index = 0
|
||||||
raise StopIteration
|
raise StopIteration
|
||||||
|
|
||||||
|
def addItem(self, key, label, valtype, value=None, unit=''):
|
||||||
|
if key in self.items.keys():
|
||||||
|
raise KeyError(f"Duplicate menu item key: '{key}'")
|
||||||
|
itm = MenuItem(valtype, label, value, unit)
|
||||||
|
self.items[key] = itm
|
||||||
|
self._index.append(key)
|
||||||
|
itm.position = self._index.index(key)
|
||||||
|
return itm
|
||||||
|
|
||||||
|
def setItemActive(self, key):
|
||||||
|
self.activeitem = self._index.index(key)
|
||||||
|
|
||||||
|
def getActiveItem(self):
|
||||||
|
return self.items[self._index[self.activeitem]]
|
||||||
|
|
||||||
|
def getItemByIndex(self, index):
|
||||||
|
return self.items[self._index[index]]
|
||||||
|
|
||||||
|
def getItemByKey(self, key):
|
||||||
|
return self.items[key]
|
||||||
|
|
||||||
|
def getItemCount(self):
|
||||||
|
return len(self.items)
|
||||||
|
|
||||||
|
def setItemDimension(self, w, h):
|
||||||
|
self._w = w
|
||||||
|
self._h = h
|
||||||
|
|
||||||
|
def getXY(self):
|
||||||
|
return (self._x, self._y)
|
||||||
|
|
||||||
|
def getRect(self):
|
||||||
|
return (self._x, self._y, self._w, self._h * len(self.items))
|
||||||
|
|
||||||
|
def getItemRect(self, index):
|
||||||
|
y = self._y + index * self._h
|
||||||
|
return (self._x, y, self._w, self._h)
|
||||||
|
|
100
pages/anchor.py
100
pages/anchor.py
|
@ -69,21 +69,19 @@ class Anchor(Page):
|
||||||
self.wind_angle = -1
|
self.wind_angle = -1
|
||||||
|
|
||||||
# Menüsteuerung für Konfiguration
|
# Menüsteuerung für Konfiguration
|
||||||
self._mnu = {
|
self._menu = Menu("Options", 20, 80)
|
||||||
# Lfd. Name, curr unit steps type: numeric, on/off
|
self._menu.setItemDimension(120, 20)
|
||||||
# TODO Das sollte eine Klasse werden!
|
newitem = self._menu.addItem("chain", "Chain out", "int", 0, "m")
|
||||||
'chain': [1, "Chain out", 0, "m", (1, 5, 10), (0, 200)],
|
newitem.setRange(0, 200, (1, 5, 10))
|
||||||
'chainmax': [2, "Chain max", 0, "m", (1, 5, 10), (0, 200)],
|
newitem = self._menu.addItem("chainmax", "Chain max", "int", self.chain_length, "m")
|
||||||
'zoom': [3, "Zoom", 50, "", (1,), (1, 8)],
|
newitem.setRange(0, 200, (1, 5, 10))
|
||||||
'range': [4, "Alarm range", 35, "m", (1, 5, 10), (0, 200)]
|
newitem = self._menu.addItem("zoom", "Zoom", "int", 2)
|
||||||
}
|
newitem.setRange(1, 8, (1,))
|
||||||
self._mnu_title = "Options"
|
newitem = self._menu.addItem("range", "Alarm range", "int", 40, "m")
|
||||||
self._mnu_x = 20
|
newitem.setRange(1, 200, (1, 5, 10))
|
||||||
self._mnu_y = 80
|
self._menu.setItemActive("chain")
|
||||||
self._mnu_w = 120
|
|
||||||
self._mnu_h = 20
|
self._test = 0
|
||||||
self._mnu_sel = 1
|
|
||||||
self.mnu_step = 1
|
|
||||||
|
|
||||||
def handle_key(self, buttonid):
|
def handle_key(self, buttonid):
|
||||||
if buttonid == 1:
|
if buttonid == 1:
|
||||||
|
@ -91,8 +89,10 @@ class Anchor(Page):
|
||||||
self.mode = 'C'
|
self.mode = 'C'
|
||||||
self.buttonlabel[2] = '#UP'
|
self.buttonlabel[2] = '#UP'
|
||||||
self.buttonlabel[3] = '#DOWN'
|
self.buttonlabel[3] = '#DOWN'
|
||||||
self.buttonlabel[4] = '[ - ]'
|
itm = self._menu.getActiveItem()
|
||||||
self.buttonlabel[5] = '[ + ]'
|
stepwidth = itm.steps[itm.step]
|
||||||
|
self.buttonlabel[4] = f"-{stepwidth}"
|
||||||
|
self.buttonlabel[5] = f"+{stepwidth}"
|
||||||
self.buttonlabel[6] = 'STEP'
|
self.buttonlabel[6] = 'STEP'
|
||||||
else:
|
else:
|
||||||
self.mode = 'N'
|
self.mode = 'N'
|
||||||
|
@ -134,16 +134,35 @@ class Anchor(Page):
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
# Konfiguration
|
# Konfiguration
|
||||||
|
itm = self._menu.getActiveItem()
|
||||||
if buttonid == 2:
|
if buttonid == 2:
|
||||||
if self._mnu_sel == 1:
|
if self._menu.activeitem == 0:
|
||||||
self._mnu_sel = len(self._mnu)
|
self._menu.activeitem = self._menu.getItemCount() - 1
|
||||||
else:
|
else:
|
||||||
self._mnu_sel -= 1
|
self._menu.activeitem -= 1
|
||||||
elif buttonid == 3:
|
elif buttonid == 3:
|
||||||
if self._mnu_sel == len(self._mnu):
|
if self._menu.activeitem == self._menu.getItemCount() - 1:
|
||||||
self._mnu_sel = 1
|
self._menu.activeitem = 0
|
||||||
else:
|
else:
|
||||||
self._mnu_sel += 1
|
self._menu.activeitem += 1
|
||||||
|
elif buttonid == 4:
|
||||||
|
# decrease value by step
|
||||||
|
stepwidth = itm.steps[itm.step]
|
||||||
|
itm.setValue(itm.value - stepwidth)
|
||||||
|
elif buttonid == 5:
|
||||||
|
# increase value by step
|
||||||
|
stepwidth = itm.steps[itm.step]
|
||||||
|
itm.setValue(itm.value + stepwidth)
|
||||||
|
elif buttonid == 6:
|
||||||
|
ns = len(itm.steps)
|
||||||
|
if ns > 1:
|
||||||
|
if itm.step < ns - 1:
|
||||||
|
itm.step += 1
|
||||||
|
else:
|
||||||
|
itm.step = 0
|
||||||
|
stepwidth = itm.steps[itm.step]
|
||||||
|
self.buttonlabel[4] = f"-{stepwidth}"
|
||||||
|
self.buttonlabel[5] = f"+{stepwidth}"
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -260,22 +279,31 @@ class Anchor(Page):
|
||||||
ctx.move_to(2, 50)
|
ctx.move_to(2, 50)
|
||||||
ctx.show_text("Anchor configuration")
|
ctx.show_text("Anchor configuration")
|
||||||
|
|
||||||
# Menüwerte initialisieren
|
|
||||||
self._mnu["chain"][2] = self.chain
|
|
||||||
self._mnu["chainmax"][2] = self.chain_length
|
|
||||||
|
|
||||||
# Menü zeichnen
|
# Menü zeichnen
|
||||||
ctx.save()
|
ctx.save()
|
||||||
ctx.set_font_size(16)
|
ctx.set_font_size(16)
|
||||||
#ctx.rectangle(100, 100, 50, 50)
|
x, y, w, h = self._menu.getRect()
|
||||||
#ctx.clip()
|
ctx.set_line_width(1)
|
||||||
for m in self._mnu.items():
|
x += 0.5 # Cairo-Fix for single pixel line
|
||||||
#ctx.move_to(self._mnu_x, self._mnu_y + 24 + m[1][0] * 16)
|
y += 0.5
|
||||||
#ctx.show_text(m[1][1])
|
ctx.save()
|
||||||
inverted = (m[1][0] == self._mnu_sel)
|
ctx.rectangle(x, y, w, h)
|
||||||
self.draw_text_boxed(ctx, self._mnu_x, self._mnu_y + self._mnu_h * (m[1][0] - 1), self._mnu_w, self._mnu_h, m[1][1], inverted)
|
ctx.clip_preserve()
|
||||||
ctx.move_to(self._mnu_x + self._mnu_w + 20 , self._mnu_y + self._mnu_h * (m[1][0] - 1))
|
ctx.stroke()
|
||||||
ctx.show_text(str(m[1][2]) + m[1][3])
|
for m in self._menu:
|
||||||
|
ix, iy, iw, ih = self._menu.getItemRect(m.position)
|
||||||
|
inverted = (m.position == self._menu.activeitem)
|
||||||
|
self.draw_text_boxed(ctx, ix, iy, iw, ih, m.label, inverted, False)
|
||||||
|
ctx.stroke()
|
||||||
|
# Werte neben dem Menü
|
||||||
|
ctx.restore()
|
||||||
|
ctx.rectangle(0, 20, 400, 360) # new clipping
|
||||||
|
ctx.clip()
|
||||||
|
self._test += 1
|
||||||
|
for m in self._menu:
|
||||||
|
ix, iy, iw, ih = self._menu.getItemRect(m.position)
|
||||||
|
ctx.move_to(ix + iw + 20, iy + ih - 4) # 5 für Unterlängen
|
||||||
|
ctx.show_text(f"{m.value} {m.unit}")
|
||||||
ctx.stroke()
|
ctx.stroke()
|
||||||
ctx.restore()
|
ctx.restore()
|
||||||
|
|
||||||
|
|
|
@ -279,17 +279,18 @@ class Page():
|
||||||
ctx.show_text(content)
|
ctx.show_text(content)
|
||||||
ctx.stroke()
|
ctx.stroke()
|
||||||
|
|
||||||
def draw_text_boxed(self, ctx, x, y, w, h, content, inverted=False):
|
def draw_text_boxed(self, ctx, x, y, w, h, content, inverted=False, border=False):
|
||||||
ctx.set_line_width(1)
|
ctx.set_line_width(1)
|
||||||
|
# Background fill
|
||||||
|
ctx.set_source_rgb(*self.fgcolor)
|
||||||
if inverted:
|
if inverted:
|
||||||
ctx.set_source_rgb(*self.fgcolor)
|
|
||||||
ctx.rectangle(x, y + 0.5, w, h)
|
ctx.rectangle(x, y + 0.5, w, h)
|
||||||
ctx.fill()
|
ctx.fill()
|
||||||
else:
|
else:
|
||||||
ctx.set_source_rgb(*self.bgcolor)
|
if border:
|
||||||
ctx.rectangle(x, y + 0.5, w, h)
|
ctx.rectangle(x + 0.5, y + 0.5, w, h)
|
||||||
ctx.stroke()
|
ctx.stroke()
|
||||||
|
# Text
|
||||||
if inverted:
|
if inverted:
|
||||||
ctx.set_source_rgb(*self.bgcolor)
|
ctx.set_source_rgb(*self.bgcolor)
|
||||||
else:
|
else:
|
||||||
|
|
Loading…
Reference in New Issue