Refactor hexagram.icons away
This commit is contained in:
parent
1255ca26f7
commit
4745176c03
3 changed files with 122 additions and 131 deletions
|
@ -11,7 +11,7 @@ from hexagram.speedo import Speedo
|
||||||
from hexagram.tacho import Tacho
|
from hexagram.tacho import Tacho
|
||||||
from hexagram.fuel import FuelGauge
|
from hexagram.fuel import FuelGauge
|
||||||
from hexagram.thermo import Thermometer
|
from hexagram.thermo import Thermometer
|
||||||
from hexagram.icons import StatusIconBox
|
from hexagram.status import StatusIconBox
|
||||||
|
|
||||||
class ShiftIndicator(Gauge):
|
class ShiftIndicator(Gauge):
|
||||||
__slots__ = 'x', 'y', 'rpm_min', 'rpm_redline', 'rpm_max',
|
__slots__ = 'x', 'y', 'rpm_min', 'rpm_redline', 'rpm_max',
|
||||||
|
|
|
@ -1,130 +0,0 @@
|
||||||
import os
|
|
||||||
import cairo
|
|
||||||
|
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
from hexagram.gauge import Gauge
|
|
||||||
from hexagram.status import VehicleStatus
|
|
||||||
from hexagram.svg import render_to_image
|
|
||||||
|
|
||||||
class ISO7000Icon():
|
|
||||||
__slots__ = 'status', 'name', 'width', 'height', 'color', 'surface',
|
|
||||||
|
|
||||||
__dirs__ = ('./icons',
|
|
||||||
'/usr/local/share/hexagram/icons'
|
|
||||||
'/usr/share/hexagram/icons')
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _locate(name: str):
|
|
||||||
for dir in ISO7000Icon.__dirs__:
|
|
||||||
path = "%s/%s.svg" % (dir, name)
|
|
||||||
|
|
||||||
if os.path.exists(path):
|
|
||||||
return path
|
|
||||||
|
|
||||||
raise FileNotFoundError(name + '.svg')
|
|
||||||
|
|
||||||
def __init__(self, status: VehicleStatus, name: str, width: float, height: float, color: str, style: Optional[str]):
|
|
||||||
self.status = status
|
|
||||||
self.name = name
|
|
||||||
self.width = width
|
|
||||||
self.height = height
|
|
||||||
self.color = color
|
|
||||||
|
|
||||||
if style is None:
|
|
||||||
style = 'rect,path,circle{stroke:%(s)s;}'
|
|
||||||
|
|
||||||
path = ISO7000Icon._locate(name)
|
|
||||||
|
|
||||||
self.surface = render_to_image(path, width, height, style % {'s': color})
|
|
||||||
|
|
||||||
def __del__(self):
|
|
||||||
if self.surface is not None:
|
|
||||||
self.surface.finish()
|
|
||||||
|
|
||||||
def draw(self, cr: cairo.Context, x: float, y: float):
|
|
||||||
cr.set_source_surface(self.surface, x, y)
|
|
||||||
cr.rectangle(x, y, self.width, self.height)
|
|
||||||
cr.fill()
|
|
||||||
|
|
||||||
class ISO7000():
|
|
||||||
__slots__ = 'icons',
|
|
||||||
|
|
||||||
__icons__ = (
|
|
||||||
(VehicleStatus.BATTERY_FAULT, 'battery', '#f00', '#rect5, #rect6 {fill: %(s)s} #rect4, path {stroke: %(s)s}'),
|
|
||||||
(VehicleStatus.BEAMS_FOG, 'beams-fog', '#0f0', '#g9 path {fill: %(s)s} #g5 path {stroke: %(s)s}'),
|
|
||||||
(VehicleStatus.BEAMS_HIGH, 'beams-high', '#00f', 'path {fill: %(s)s; stroke: %(s)s}'),
|
|
||||||
(VehicleStatus.BEAMS_LOW, 'beams-low', '#0f0', 'path {fill: %(s)s; stroke: %(s)s}'),
|
|
||||||
(VehicleStatus.BEAMS_PARKING, 'beams-parking', '#ff0'),
|
|
||||||
(VehicleStatus.BELT, 'belt', '#f00', 'path {fill: %(s)s}'),
|
|
||||||
(VehicleStatus.COLD, 'cold', '#eef'),
|
|
||||||
(VehicleStatus.COLLISION, 'collision', '#f00', 'path {stroke: %(s)s}'),
|
|
||||||
(VehicleStatus.COOLANT_LOW, 'coolant', '#fa0', 'path, circle, rect {fill: %(s)s} #g9 path {stroke: %(s)s}'),
|
|
||||||
(VehicleStatus.COOLANT_OVERHEAT, 'coolant', '#f00', 'path, circle, rect {fill: %(s)s} #g9 path {stroke: %(s)s}'),
|
|
||||||
(VehicleStatus.CRUISE, 'cruise', '#0f0', 'path, circle {fill: %(s)s; stroke: %(s)s}'),
|
|
||||||
(VehicleStatus.FUEL_LOW, 'fuel', '#fa0', '#g9 * {stroke: %(s)s} #path9 {fill: %(s)s}'),
|
|
||||||
(VehicleStatus.LANEKEEP_OFF, 'lane-departure', '#fa0'),
|
|
||||||
(VehicleStatus.OIL_LOW, 'oil', '#fa0', 'path {fill: %(s)s; stroke: %(s)s}'),
|
|
||||||
(VehicleStatus.OIL_OVERHEAT, 'oil', '#f00', 'path {fill: %(s)s; stroke: %(s)s}'),
|
|
||||||
(VehicleStatus.PARKING_BRAKE_ON, 'parking', '#fa0', '#path6, #path5 {stroke: %(s)s} circle {stroke: %(s)s} #path7 {fill: %(s)s}'),
|
|
||||||
(VehicleStatus.PARKING_BRAKE_FAULT, 'parking', '#f00', '#path6, #path5 {stroke: %(s)s} circle {stroke: %(s)s} #path7 {fill: %(s)s}'),
|
|
||||||
(VehicleStatus.STABILITY_OFF, 'stability', '#fa0', '#path9, #path8, #path7, #path6, #path5 {fill: %(s)s} #path10 {stroke: %(s)s}'),
|
|
||||||
(VehicleStatus.TPMS_WARNING, 'tpms', '#fa0', 'path, circle {fill: %(s)s}'),
|
|
||||||
(VehicleStatus.WIPER_WASHER_LOW, 'wiper-washer', '#fa0'),
|
|
||||||
)
|
|
||||||
|
|
||||||
def __init__(self, width: float, height: float):
|
|
||||||
self.icons = dict()
|
|
||||||
|
|
||||||
for item in self.__icons__:
|
|
||||||
status, name, color = item[0:3]
|
|
||||||
style = 'rect,path,circle{stroke:%(s)s;}' if len(item) < 4 else item[3]
|
|
||||||
|
|
||||||
self.icons[status.value] = ISO7000Icon(status,
|
|
||||||
name,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
color,
|
|
||||||
style)
|
|
||||||
|
|
||||||
class StatusIconBox(Gauge):
|
|
||||||
__slots__ = 'x', 'y', 'width', 'height', 'iso7000', 'value',
|
|
||||||
|
|
||||||
ICON_WIDTH = 48
|
|
||||||
ICON_HEIGHT = 48
|
|
||||||
|
|
||||||
def __init__(self, x: float, y: float, width: float, height: float):
|
|
||||||
self.x = x
|
|
||||||
self.y = y
|
|
||||||
self.width = width
|
|
||||||
self.height = height
|
|
||||||
self.iso7000 = ISO7000(self.ICON_WIDTH, self.ICON_HEIGHT)
|
|
||||||
self.value = VehicleStatus.OK.value
|
|
||||||
|
|
||||||
def reset(self):
|
|
||||||
self.value = VehicleStatus.OK.value
|
|
||||||
|
|
||||||
def set_status(self, status: VehicleStatus):
|
|
||||||
self.value |= status.value
|
|
||||||
|
|
||||||
def clear_status(self, status: VehicleStatus):
|
|
||||||
self.value &= ~status.value
|
|
||||||
|
|
||||||
def draw_bg(self, cr: cairo.Context):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def draw_fg(self, cr: cairo.Context):
|
|
||||||
x, y = 0, 0
|
|
||||||
|
|
||||||
for status_value in self.iso7000.icons:
|
|
||||||
icon = self.iso7000.icons[status_value]
|
|
||||||
|
|
||||||
if self.value & status_value:
|
|
||||||
if icon is not None:
|
|
||||||
icon.draw(cr, self.x + x, self.y + y)
|
|
||||||
|
|
||||||
x += self.ICON_WIDTH
|
|
||||||
|
|
||||||
if x >= self.width:
|
|
||||||
x = 0
|
|
||||||
y += self.ICON_HEIGHT
|
|
|
@ -1,4 +1,11 @@
|
||||||
|
import os
|
||||||
import enum
|
import enum
|
||||||
|
import cairo
|
||||||
|
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from hexagram.svg import render_to_image
|
||||||
|
from hexagram.gauge import Gauge
|
||||||
|
|
||||||
class VehicleStatus(enum.Enum):
|
class VehicleStatus(enum.Enum):
|
||||||
OK = 0
|
OK = 0
|
||||||
|
@ -50,3 +57,117 @@ class VehicleStatus(enum.Enum):
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.__strings__.get(self.value, "unknown")
|
return self.__strings__.get(self.value, "unknown")
|
||||||
|
|
||||||
|
class StatusIcon():
|
||||||
|
__slots__ = 'status', 'name', 'width', 'height', 'color', 'surface',
|
||||||
|
|
||||||
|
__dirs__ = ('./icons',
|
||||||
|
'/usr/local/share/hexagram/icons'
|
||||||
|
'/usr/share/hexagram/icons')
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _locate(name: str):
|
||||||
|
for dir in StatusIcon.__dirs__:
|
||||||
|
path = "%s/%s.svg" % (dir, name)
|
||||||
|
|
||||||
|
if os.path.exists(path):
|
||||||
|
return path
|
||||||
|
|
||||||
|
raise FileNotFoundError(name + '.svg')
|
||||||
|
|
||||||
|
def __init__(self, status: VehicleStatus, name: str, width: float, height: float, color: str, style: Optional[str]):
|
||||||
|
self.status = status
|
||||||
|
self.name = name
|
||||||
|
self.width = width
|
||||||
|
self.height = height
|
||||||
|
self.color = color
|
||||||
|
|
||||||
|
if style is None:
|
||||||
|
style = 'rect,path,circle{stroke:%(s)s;}'
|
||||||
|
|
||||||
|
path = StatusIcon._locate(name)
|
||||||
|
|
||||||
|
self.surface = render_to_image(path, width, height, style % {'s': color})
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
if self.surface is not None:
|
||||||
|
self.surface.finish()
|
||||||
|
|
||||||
|
def draw(self, cr: cairo.Context, x: float, y: float):
|
||||||
|
cr.set_source_surface(self.surface, x, y)
|
||||||
|
cr.rectangle(x, y, self.width, self.height)
|
||||||
|
cr.fill()
|
||||||
|
|
||||||
|
class StatusIconBox(Gauge):
|
||||||
|
__slots__ = 'x', 'y', 'width', 'height', 'icons', 'value',
|
||||||
|
|
||||||
|
__icons__ = (
|
||||||
|
(VehicleStatus.BATTERY_FAULT, 'battery', '#f00', '#rect5, #rect6 {fill: %(s)s} #rect4, path {stroke: %(s)s}'),
|
||||||
|
(VehicleStatus.BEAMS_FOG, 'beams-fog', '#0f0', '#g9 path {fill: %(s)s} #g5 path {stroke: %(s)s}'),
|
||||||
|
(VehicleStatus.BEAMS_HIGH, 'beams-high', '#00f', 'path {fill: %(s)s; stroke: %(s)s}'),
|
||||||
|
(VehicleStatus.BEAMS_LOW, 'beams-low', '#0f0', 'path {fill: %(s)s; stroke: %(s)s}'),
|
||||||
|
(VehicleStatus.BEAMS_PARKING, 'beams-parking', '#ff0'),
|
||||||
|
(VehicleStatus.BELT, 'belt', '#f00', 'path {fill: %(s)s}'),
|
||||||
|
(VehicleStatus.COLD, 'cold', '#eef'),
|
||||||
|
(VehicleStatus.COLLISION, 'collision', '#f00', 'path {stroke: %(s)s}'),
|
||||||
|
(VehicleStatus.COOLANT_LOW, 'coolant', '#fa0', 'path, circle, rect {fill: %(s)s} #g9 path {stroke: %(s)s}'),
|
||||||
|
(VehicleStatus.COOLANT_OVERHEAT, 'coolant', '#f00', 'path, circle, rect {fill: %(s)s} #g9 path {stroke: %(s)s}'),
|
||||||
|
(VehicleStatus.CRUISE, 'cruise', '#0f0', 'path, circle {fill: %(s)s; stroke: %(s)s}'),
|
||||||
|
(VehicleStatus.FUEL_LOW, 'fuel', '#fa0', '#g9 * {stroke: %(s)s} #path9 {fill: %(s)s}'),
|
||||||
|
(VehicleStatus.LANEKEEP_OFF, 'lane-departure', '#fa0'),
|
||||||
|
(VehicleStatus.OIL_LOW, 'oil', '#fa0', 'path {fill: %(s)s; stroke: %(s)s}'),
|
||||||
|
(VehicleStatus.OIL_OVERHEAT, 'oil', '#f00', 'path {fill: %(s)s; stroke: %(s)s}'),
|
||||||
|
(VehicleStatus.PARKING_BRAKE_ON, 'parking', '#fa0', '#path6, #path5 {stroke: %(s)s} circle {stroke: %(s)s} #path7 {fill: %(s)s}'),
|
||||||
|
(VehicleStatus.PARKING_BRAKE_FAULT, 'parking', '#f00', '#path6, #path5 {stroke: %(s)s} circle {stroke: %(s)s} #path7 {fill: %(s)s}'),
|
||||||
|
(VehicleStatus.STABILITY_OFF, 'stability', '#fa0', '#path9, #path8, #path7, #path6, #path5 {fill: %(s)s} #path10 {stroke: %(s)s}'),
|
||||||
|
(VehicleStatus.TPMS_WARNING, 'tpms', '#fa0', 'path, circle {fill: %(s)s}'),
|
||||||
|
(VehicleStatus.WIPER_WASHER_LOW, 'wiper-washer', '#fa0'),
|
||||||
|
)
|
||||||
|
|
||||||
|
ICON_WIDTH = 48
|
||||||
|
ICON_HEIGHT = 48
|
||||||
|
|
||||||
|
def __init__(self, x: float, y: float, width: float, height: float):
|
||||||
|
self.x = x
|
||||||
|
self.y = y
|
||||||
|
self.width = width
|
||||||
|
self.height = height
|
||||||
|
self.value = VehicleStatus.OK.value
|
||||||
|
self.icons: dict[int, StatusIcon] = dict()
|
||||||
|
|
||||||
|
for item in self.__icons__:
|
||||||
|
status, name, color = item[0:3]
|
||||||
|
style = 'rect,path,circle{stroke:%(s)s;}' if len(item) < 4 else item[3]
|
||||||
|
|
||||||
|
self.icons[status.value] = StatusIcon(status, name,
|
||||||
|
self.ICON_WIDTH,
|
||||||
|
self.ICON_HEIGHT,
|
||||||
|
color, style)
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
self.value = VehicleStatus.OK.value
|
||||||
|
|
||||||
|
def set_status(self, status: VehicleStatus):
|
||||||
|
self.value |= status.value
|
||||||
|
|
||||||
|
def clear_status(self, status: VehicleStatus):
|
||||||
|
self.value &= ~status.value
|
||||||
|
|
||||||
|
def draw_bg(self, cr: cairo.Context):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def draw_fg(self, cr: cairo.Context):
|
||||||
|
x, y = 0, 0
|
||||||
|
|
||||||
|
for status_value in self.icons:
|
||||||
|
icon = self.icons[status_value]
|
||||||
|
|
||||||
|
if self.value & status_value:
|
||||||
|
if icon is not None:
|
||||||
|
icon.draw(cr, self.x + x, self.y + y)
|
||||||
|
|
||||||
|
x += self.ICON_WIDTH
|
||||||
|
|
||||||
|
if x >= self.width:
|
||||||
|
x = 0
|
||||||
|
y += self.ICON_HEIGHT
|
||||||
|
|
Loading…
Add table
Reference in a new issue