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()
 |