64 lines
1.8 KiB
Python
64 lines
1.8 KiB
Python
import os
|
|
import enum
|
|
import cairo
|
|
|
|
from hexagram.svg import render_to_image
|
|
|
|
class Icon():
|
|
__slots__ = 'name', 'width', 'height', 'style', 'variants', \
|
|
'_path', '_surfaces',
|
|
|
|
__dirs__ = ('./icons',
|
|
'/usr/local/share/hexagram/icons'
|
|
'/usr/share/hexagram/icons')
|
|
|
|
@staticmethod
|
|
def _locate(name: str):
|
|
for dir in Icon.__dirs__:
|
|
path = "%s/%s.svg" % (dir, name)
|
|
|
|
if os.path.exists(path):
|
|
return path
|
|
|
|
raise FileNotFoundError(name + '.svg')
|
|
|
|
STYLE = 'rect,path,circle{stroke:%(s)s;}'
|
|
|
|
def __init__(self, name: str, width: float, height: float, variants: dict, style: str=STYLE):
|
|
self.name = name
|
|
self.width = width
|
|
self.height = height
|
|
self.style = style
|
|
self.variants = variants
|
|
self._path = Icon._locate(name)
|
|
self._surfaces: dict[enum.Enum, cairo.ImageSurface] = dict()
|
|
|
|
def __del__(self):
|
|
for key in self._surfaces:
|
|
self._surfaces[key].finish()
|
|
|
|
def _surface(self, status) -> cairo.ImageSurface:
|
|
surface = self._surfaces.get(status)
|
|
|
|
if surface is not None:
|
|
return surface
|
|
|
|
color = self.variants[status]
|
|
surface = render_to_image(self._path,
|
|
self.width,
|
|
self.height,
|
|
self.style % {'s': color})
|
|
|
|
self._surfaces[status] = surface
|
|
|
|
return surface
|
|
|
|
def drawable(self, status: enum.Enum):
|
|
return status in self.variants
|
|
|
|
def draw(self, cr: cairo.Context, x: float, y: float, status):
|
|
surface = self._surface(status)
|
|
|
|
cr.set_source_surface(surface, x, y)
|
|
cr.rectangle(x, y, self.width, self.height)
|
|
cr.fill()
|