Ankerseite: Werte über Tastatur änderbar
This commit is contained in:
parent
986d222a98
commit
dafcfaca6b
110
cfgmenu.py
110
cfgmenu.py
|
@ -5,44 +5,94 @@ Menüsystem für Konfiguration(en)
|
|||
|
||||
class MenuItem():
|
||||
|
||||
def __init__(self, itmname):
|
||||
self.name = itmname
|
||||
self.label = None
|
||||
self.value = None
|
||||
self.steps = (1,)
|
||||
def __init__(self, valtype, label, value=None, unit=''):
|
||||
validtypes = ('int', 'bool')
|
||||
valtype = valtype.lower() # Groß- und Kleinschreibung lassen wir gemischt zu
|
||||
if valtype not in validtypes:
|
||||
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):
|
||||
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():
|
||||
|
||||
def __init__(self):
|
||||
title = None
|
||||
x = 0
|
||||
y = 0
|
||||
w = 100
|
||||
h = 20
|
||||
items = []
|
||||
itm_active = -1 # nothing activated
|
||||
self._index = -1
|
||||
|
||||
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 __init__(self, title, x, y):
|
||||
self.title = title
|
||||
self.items = {} # Items über Schlüssel zugreifbar
|
||||
self.activeitem = -1 # Noch nichts aktiv
|
||||
self._x = x
|
||||
self._y = y
|
||||
self._w = 100
|
||||
self._h = 20
|
||||
self._index = [] # Mapping zwischen Index(Position) und Schlüssel
|
||||
self._iter_index = 0
|
||||
|
||||
def __iter__(self):
|
||||
return self
|
||||
|
||||
def __next__(self):
|
||||
if self._index < self._class_size:
|
||||
itm = items[self._index]
|
||||
self._index += 1
|
||||
if self._iter_index < len(self.items):
|
||||
itm = self.items[self._index[self._iter_index]]
|
||||
self._iter_index += 1
|
||||
return itm
|
||||
raise StopIteration
|
||||
self._iter_index = 0
|
||||
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
|
||||
|
||||
# Menüsteuerung für Konfiguration
|
||||
self._mnu = {
|
||||
# Lfd. Name, curr unit steps type: numeric, on/off
|
||||
# TODO Das sollte eine Klasse werden!
|
||||
'chain': [1, "Chain out", 0, "m", (1, 5, 10), (0, 200)],
|
||||
'chainmax': [2, "Chain max", 0, "m", (1, 5, 10), (0, 200)],
|
||||
'zoom': [3, "Zoom", 50, "", (1,), (1, 8)],
|
||||
'range': [4, "Alarm range", 35, "m", (1, 5, 10), (0, 200)]
|
||||
}
|
||||
self._mnu_title = "Options"
|
||||
self._mnu_x = 20
|
||||
self._mnu_y = 80
|
||||
self._mnu_w = 120
|
||||
self._mnu_h = 20
|
||||
self._mnu_sel = 1
|
||||
self.mnu_step = 1
|
||||
self._menu = Menu("Options", 20, 80)
|
||||
self._menu.setItemDimension(120, 20)
|
||||
newitem = self._menu.addItem("chain", "Chain out", "int", 0, "m")
|
||||
newitem.setRange(0, 200, (1, 5, 10))
|
||||
newitem = self._menu.addItem("chainmax", "Chain max", "int", self.chain_length, "m")
|
||||
newitem.setRange(0, 200, (1, 5, 10))
|
||||
newitem = self._menu.addItem("zoom", "Zoom", "int", 2)
|
||||
newitem.setRange(1, 8, (1,))
|
||||
newitem = self._menu.addItem("range", "Alarm range", "int", 40, "m")
|
||||
newitem.setRange(1, 200, (1, 5, 10))
|
||||
self._menu.setItemActive("chain")
|
||||
|
||||
self._test = 0
|
||||
|
||||
def handle_key(self, buttonid):
|
||||
if buttonid == 1:
|
||||
|
@ -91,8 +89,10 @@ class Anchor(Page):
|
|||
self.mode = 'C'
|
||||
self.buttonlabel[2] = '#UP'
|
||||
self.buttonlabel[3] = '#DOWN'
|
||||
self.buttonlabel[4] = '[ - ]'
|
||||
self.buttonlabel[5] = '[ + ]'
|
||||
itm = self._menu.getActiveItem()
|
||||
stepwidth = itm.steps[itm.step]
|
||||
self.buttonlabel[4] = f"-{stepwidth}"
|
||||
self.buttonlabel[5] = f"+{stepwidth}"
|
||||
self.buttonlabel[6] = 'STEP'
|
||||
else:
|
||||
self.mode = 'N'
|
||||
|
@ -134,16 +134,35 @@ class Anchor(Page):
|
|||
return True
|
||||
else:
|
||||
# Konfiguration
|
||||
itm = self._menu.getActiveItem()
|
||||
if buttonid == 2:
|
||||
if self._mnu_sel == 1:
|
||||
self._mnu_sel = len(self._mnu)
|
||||
if self._menu.activeitem == 0:
|
||||
self._menu.activeitem = self._menu.getItemCount() - 1
|
||||
else:
|
||||
self._mnu_sel -= 1
|
||||
self._menu.activeitem -= 1
|
||||
elif buttonid == 3:
|
||||
if self._mnu_sel == len(self._mnu):
|
||||
self._mnu_sel = 1
|
||||
if self._menu.activeitem == self._menu.getItemCount() - 1:
|
||||
self._menu.activeitem = 0
|
||||
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 False
|
||||
|
||||
|
@ -260,22 +279,31 @@ class Anchor(Page):
|
|||
ctx.move_to(2, 50)
|
||||
ctx.show_text("Anchor configuration")
|
||||
|
||||
# Menüwerte initialisieren
|
||||
self._mnu["chain"][2] = self.chain
|
||||
self._mnu["chainmax"][2] = self.chain_length
|
||||
|
||||
# Menü zeichnen
|
||||
ctx.save()
|
||||
ctx.set_font_size(16)
|
||||
#ctx.rectangle(100, 100, 50, 50)
|
||||
#ctx.clip()
|
||||
for m in self._mnu.items():
|
||||
#ctx.move_to(self._mnu_x, self._mnu_y + 24 + m[1][0] * 16)
|
||||
#ctx.show_text(m[1][1])
|
||||
inverted = (m[1][0] == self._mnu_sel)
|
||||
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.move_to(self._mnu_x + self._mnu_w + 20 , self._mnu_y + self._mnu_h * (m[1][0] - 1))
|
||||
ctx.show_text(str(m[1][2]) + m[1][3])
|
||||
x, y, w, h = self._menu.getRect()
|
||||
ctx.set_line_width(1)
|
||||
x += 0.5 # Cairo-Fix for single pixel line
|
||||
y += 0.5
|
||||
ctx.save()
|
||||
ctx.rectangle(x, y, w, h)
|
||||
ctx.clip_preserve()
|
||||
ctx.stroke()
|
||||
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.restore()
|
||||
|
||||
|
|
|
@ -279,17 +279,18 @@ class Page():
|
|||
ctx.show_text(content)
|
||||
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)
|
||||
# Background fill
|
||||
ctx.set_source_rgb(*self.fgcolor)
|
||||
if inverted:
|
||||
ctx.set_source_rgb(*self.fgcolor)
|
||||
ctx.rectangle(x, y + 0.5, w, h)
|
||||
ctx.fill()
|
||||
else:
|
||||
ctx.set_source_rgb(*self.bgcolor)
|
||||
ctx.rectangle(x, y + 0.5, w, h)
|
||||
ctx.stroke()
|
||||
|
||||
if border:
|
||||
ctx.rectangle(x + 0.5, y + 0.5, w, h)
|
||||
ctx.stroke()
|
||||
# Text
|
||||
if inverted:
|
||||
ctx.set_source_rgb(*self.bgcolor)
|
||||
else:
|
||||
|
|
Loading…
Reference in New Issue