from typing import Optional
import webcolors
from PIL import Image, ImageDraw
from pydantic import Field
from todays_paper_web.widgets import registerView, View
from todays_paper_web.widgets.params import Color
from todays_paper_web.widgets.view import ViewParams
[docs]
class LineParams(ViewParams):
# x/y (the line's own start point, defaulting to 0) come from
# ViewParams - the same attributes a parent container reads to
# position this element are what render() below uses as its start
# coordinate, which is why the two never disagree with each other.
x2: Optional[int] = Field(
None, description="The line's end x coordinate; defaults to `x` (a zero-length line)."
)
y2: Optional[int] = Field(None, description="The line's end y coordinate; defaults to `y`.")
width: int = Field(1, description="Stroke thickness in pixels.")
color: Color = Field(
default_factory=lambda: webcolors.name_to_rgb("black"), description="Line color."
)
@registerView("line")
class LineView(View):
Params = LineParams
def render(self):
x1 = self.params.x or 0
y1 = self.params.y or 0
x2 = self.params.x2 if self.params.x2 is not None else x1
y2 = self.params.y2 if self.params.y2 is not None else y1
width = max(abs(x2 - x1), self.params.width)
height = max(abs(y2 - y1), self.params.width)
img = Image.new("RGBA", (width, height), (0, 0, 0, 0))
draw = ImageDraw.Draw(img)
color = (self.params.color.red, self.params.color.green, self.params.color.blue, 255)
dx = abs(x2 - x1)
dy = abs(y2 - y1)
draw.line((0, 0, dx, dy), fill=color, width=self.params.width)
return img