234 lines
7.6 KiB
Python
234 lines
7.6 KiB
Python
"""
|
|
|
|
Basisklasse für alle Darstellungsseiten
|
|
|
|
Hinweise zu Cairo:
|
|
Das Koordinatensystem geht von (0, 0) links oben bis (400, 300) rechts unten.
|
|
Um exakte Pixel zu treffen müssen Koordinaten mit Offset 0.5 verwendet werden.
|
|
|
|
"""
|
|
import os
|
|
import cairo
|
|
import math
|
|
from datetime import datetime
|
|
|
|
class Page():
|
|
|
|
pageno = 1 # Nummer der aktuell sichtbaren Seite
|
|
backlight = False
|
|
color_normal = "dcdcdc" # Standardhintergrund
|
|
color_lighted = "d89090" # Hintergrund im Nachtmodus
|
|
|
|
bgcolor = (0.86, 0.86, 0.86)
|
|
fgcolor = (0, 0, 0)
|
|
|
|
@staticmethod
|
|
def hexcolor(hexstr):
|
|
if (len(hexstr) != 6) or (not all(c.lower in '0123456789abcdef' for c in hexstr)):
|
|
raise ValueError('Not a valid RGB Hexstring')
|
|
else:
|
|
return(int(hexstr[0:2], 16) / 255.0,
|
|
int(hexstr[2:4], 16) / 255.0,
|
|
int(hexstr[4:6], 16) / 255.0)
|
|
|
|
@staticmethod
|
|
def rotate (origin, points, angle):
|
|
# operates on tuples, angle in degrees
|
|
ox, oy = origin
|
|
phi = math.radians(angle)
|
|
fs = math.sin(phi)
|
|
fc = math.cos(phi)
|
|
rotated = []
|
|
for x, y in points:
|
|
dx = x - ox
|
|
dy = y - oy
|
|
rotated.append((ox + fc * dx - fs * dy, oy + fs * dx + fc * dy))
|
|
return rotated
|
|
|
|
def __init__(self, pageno, cfg, boatdata):
|
|
self.pageno = pageno
|
|
self.cfg = cfg
|
|
self.bd = boatdata
|
|
self.header = True
|
|
self.footer = True
|
|
self.hbled = False # Heartbeat LED
|
|
self.hbfreq = 1000 # Heartbeat Frequenz in ms
|
|
self.keylock = False
|
|
self.icon = {}
|
|
self.icon['PREV'] = cairo.ImageSurface.create_from_png(os.path.join(cfg['imgpath'], "arrow_l1.png"))
|
|
self.icon['NEXT'] = cairo.ImageSurface.create_from_png(os.path.join(cfg['imgpath'], "arrow_r1.png"))
|
|
self.icon['ILUM'] = cairo.ImageSurface.create_from_png(os.path.join(cfg['imgpath'], "lighton.png"))
|
|
self.sym_lock = cairo.ImageSurface.create_from_png(os.path.join(cfg['imgpath'], "lock.png"))
|
|
self.sym_swipe = cairo.ImageSurface.create_from_png(os.path.join(cfg['imgpath'], "swipe.png"))
|
|
self.buttonlabel = {
|
|
1: '',
|
|
2: '',
|
|
3: '#PREV',
|
|
4: '#NEXT',
|
|
5: '',
|
|
6: '#ILUM'
|
|
}
|
|
|
|
def handle_key(self, buttonid):
|
|
"""
|
|
Diese Methode sollte in der Detailseite überladen werden
|
|
"""
|
|
print(f"Button no. {buttonid} ignored")
|
|
return False
|
|
|
|
def heartbeat(self, ctx):
|
|
"""
|
|
Wie ausschalten bei Seitenwechsel?
|
|
"""
|
|
ctx.save()
|
|
if self.hbled:
|
|
ctx.set_source_rgb(0, 0, 0)
|
|
else:
|
|
ctx.set_source_rgb(0.86, 0.86, 0.86) # 0xdcdcdc
|
|
ctx.arc(210, 9, 6, 0, math.pi*2)
|
|
ctx.fill()
|
|
ctx.restore()
|
|
self.hbled = not self.hbled
|
|
|
|
def draw_header(self, ctx):
|
|
"""
|
|
Mögliche Zeichen für aktivierte Funktionen
|
|
AP - Accesspoint ist aktiv
|
|
WIFI - WIFI-Client
|
|
TCP
|
|
N2K - NMEA2000
|
|
183
|
|
USB
|
|
GPS - GPS Fix vorhanden
|
|
# TODO Umstellung auf Symbole je 16 Pixel zum Platz sparen
|
|
Neu: Nummer der aktiven Seite (1 - 10)
|
|
"""
|
|
ctx.select_font_face("Ubuntu", cairo.FontSlant.NORMAL, cairo.FontWeight.BOLD)
|
|
ctx.set_font_size(16)
|
|
ctx.move_to(0.5, 14.5)
|
|
ctx.show_text(f"N2K GPS")
|
|
ctx.stroke()
|
|
|
|
# Seitennummer neue Darstellung
|
|
ctx.set_line_width(1)
|
|
ctx.move_to(170.5, 1.5)
|
|
ctx.line_to(190.5, 1.5)
|
|
ctx.line_to(190.5, 16.5)
|
|
ctx.line_to(170.5, 16.5)
|
|
ctx.line_to(170.5, 1.5)
|
|
ctx.stroke()
|
|
self.draw_text_center(ctx, 180, 9.5, str(self.pageno))
|
|
|
|
# Tastenstatus
|
|
ctx.save()
|
|
if self.keylock:
|
|
ctx.set_source_surface(self.sym_lock, 150, 1)
|
|
else:
|
|
ctx.set_source_surface(self.sym_swipe, 150, 1)
|
|
ctx.paint()
|
|
ctx.restore()
|
|
|
|
# Heartbeat
|
|
self.heartbeat(ctx)
|
|
|
|
# Datum und Uhrzeit
|
|
ctx.move_to(230, 14.5)
|
|
ctx.show_text(datetime.today().strftime('%H:%M %Y-%m-%d LOT'))
|
|
ctx.stroke()
|
|
|
|
def draw_footer(self, ctx):
|
|
"""
|
|
Nur Belegung der Buttons (label[1] bis label[6])
|
|
"""
|
|
ctx.select_font_face("AtariST8x16SystemFont")
|
|
#ctx.select_font_face("Ubuntu", cairo.FontSlant.NORMAL, cairo.FontWeight.BOLD)
|
|
ctx.set_font_size(16)
|
|
x = (35, 101, 167, 233, 299, 365)
|
|
y = 294
|
|
for i in range(6):
|
|
if len(self.buttonlabel[i+1]) > 0 :
|
|
if self.buttonlabel[i+1][0] == "#":
|
|
# Symbol verwenden 16x16 Pixel
|
|
ctx.save()
|
|
key = self.buttonlabel[i+1][1:]
|
|
ctx.set_source_surface(self.icon[key], x[i]-8, y-13)
|
|
ctx.paint()
|
|
ctx.restore()
|
|
else:
|
|
text = "[ {} ]".format(self.buttonlabel[i+1])
|
|
w = ctx.text_extents(text).width
|
|
ctx.move_to(x[i] - w/2, y)
|
|
ctx.show_text(text)
|
|
ctx.stroke()
|
|
|
|
def clear(self):
|
|
ctx.set_source_rgb(1, 1, 1)
|
|
ctx.rectangle(0, 0, 399, 299)
|
|
ctx.fill()
|
|
ctx.set_source_rgb(0, 0, 0)
|
|
|
|
def draw_text_center(self, ctx, x, y, content, rotate=False, baseline=False, fill=False, fix1=False):
|
|
"""
|
|
Korrektur für DSEG7: Die Breite der 1 ist gleich 0.289 * Breite der anderen Ziffern
|
|
Da der Leerraum bei der Ausgabe mit berücksichtigt wird, muß die tatsächliche
|
|
Ausgabeposition links von der Mitte sein um (1 - 0.289) * Breite (=0.711)
|
|
Zusätzlich muß der Abstand zwischen der 1 und dem nachfolgenden Zeichen berücksichtigt
|
|
werden
|
|
"""
|
|
if fix1 and content[0] == '1':
|
|
print("Fix1")
|
|
ext1 = ctx.text_extents('1')
|
|
w1 = 0.289 * ext1.width
|
|
dx = ext1.width - w1
|
|
ext = ctx.text_extents(content[1:])
|
|
else:
|
|
ext = ctx.text_extents(content)
|
|
if fill:
|
|
ctx.set_source_rgb(*self.bgcolor)
|
|
xf = x + ext.x_bearing - 2
|
|
yf = y + ext.height / 2 + ext.y_bearing - 2
|
|
wf = ext.width + 4
|
|
if fix1:
|
|
wf += w1
|
|
hf = ext.height + 4
|
|
ctx.rectangle(xf, yf, wf, hf)
|
|
ctx.fill()
|
|
ctx.set_source_rgb(*self.fgcolor)
|
|
if rotate:
|
|
w = ext[2]
|
|
if fix1 and content[0] == '1':
|
|
w += w1
|
|
x = x - dx
|
|
if baseline:
|
|
ctx.move_to(x - w / 2.0, y)
|
|
else:
|
|
ctx.move_to(x - w / 2.0, y + ext[2] / 2.0)
|
|
ctx.save()
|
|
ctx.rotate(1.5 * math.pi)
|
|
ctx.show_text(content)
|
|
ctx.restore()
|
|
else:
|
|
w = ext.width
|
|
if fix1 and content[0] == '1':
|
|
w += w1
|
|
x = x - dx
|
|
if baseline:
|
|
ctx.move_to(x - w / 2.0, y)
|
|
else:
|
|
ctx.move_to(x - w / 2.0, y + ext[3] / 2.0)
|
|
ctx.show_text(content)
|
|
ctx.stroke()
|
|
|
|
def draw_text_ralign(self, ctx, x, y, content, fix1=False):
|
|
if fix1 and content[0] == '1':
|
|
w1 = ctx.text_extents('1')[2] * 0.289
|
|
ext = ctx.text_extents(content[1:])
|
|
w = ext[2] + w1
|
|
x = x - dx
|
|
else:
|
|
ext = ctx.text_extents(content)
|
|
w = ext[2]
|
|
ctx.move_to(x - w, y)
|
|
ctx.show_text(content)
|
|
ctx.stroke()
|