63 lines
1.8 KiB
Python
63 lines
1.8 KiB
Python
import math
|
|
import cairo
|
|
|
|
from hexagram.gauge import Gauge
|
|
|
|
class Dial(Gauge):
|
|
__slots = 'x', 'y', 'radius', 'min_angle', 'max_angle', 'max_value',
|
|
|
|
ANGLE_OFFSET = math.pi / 2
|
|
|
|
BEZEL_WIDTH = 16
|
|
BEZEL_GRADIENT_STOPS = (
|
|
(0, 1.0, 0.4, 1.0, 1.0),
|
|
(1, 0.4, 0.0, 0.4, 0.0)
|
|
)
|
|
|
|
def __init__(self, x: float, y: float, radius: float, min_angle: float, max_angle: float, max_value: float):
|
|
self.x = x
|
|
self.y = y
|
|
self.radius = radius
|
|
self.min_angle = min_angle
|
|
self.max_angle = max_angle
|
|
self.max_value = max_value
|
|
|
|
def _gradient(self):
|
|
gradient = cairo.LinearGradient(self.x - self.radius,
|
|
self.y - self.radius,
|
|
self.x + self.radius,
|
|
self.y + self.radius)
|
|
|
|
for stop in self.BEZEL_GRADIENT_STOPS:
|
|
gradient.add_color_stop_rgba(*stop)
|
|
|
|
return gradient
|
|
|
|
def draw_number(self, cr: cairo.Context, radius: float, value: float, text: str):
|
|
scale = value / self.max_value
|
|
angle = self.min_angle + ((self.max_angle - self.min_angle) * scale) - self.ANGLE_OFFSET
|
|
|
|
cr.set_source_rgb(1, 1, 1)
|
|
cr.move_to(self.x + radius * self.radius * math.cos(angle) - 20,
|
|
self.y + radius * self.radius * math.sin(angle))
|
|
|
|
cr.show_text(text)
|
|
cr.stroke()
|
|
|
|
def draw_bg(self, cr: cairo.Context):
|
|
arc = (self.x,
|
|
self.y,
|
|
self.radius - self.BEZEL_WIDTH,
|
|
0,
|
|
2.0 * math.pi)
|
|
|
|
# Gauge face
|
|
cr.set_source_rgba(0, 0, 0, 1)
|
|
cr.arc(*arc)
|
|
cr.fill()
|
|
|
|
# Gauge bezel
|
|
cr.set_source(self._gradient())
|
|
cr.set_line_width(self.BEZEL_WIDTH)
|
|
cr.arc(*arc)
|
|
cr.stroke()
|