Icon in document tree
This commit is contained in:
@@ -1,10 +1,13 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from PySide6.QtCore import QRectF
|
||||
from PySide6.QtCore import QRectF, QSize, Qt
|
||||
from PySide6.QtGui import QBrush, QColor, QFont, QIcon, QPainter, QPen, QPixmap
|
||||
|
||||
from bedit_gui.models import Icon, Line, Rectangle, Text
|
||||
from bedit_core.models import Port, PortID, SignalDirection
|
||||
from bedit_gui.models import Icon, Line, LineType, Rectangle, Text
|
||||
|
||||
PORT_SIZE = 16
|
||||
DEFAULT_ICON_SIZE = QSize(48, 48)
|
||||
|
||||
|
||||
def get_bounding_box(icon: Icon) -> QRectF:
|
||||
@@ -30,3 +33,64 @@ def get_bounding_box(icon: Icon) -> QRectF:
|
||||
right = max(point[0] for point in points)
|
||||
bottom = max(point[1] for point in points)
|
||||
return QRectF(left, top, right - left, bottom - top)
|
||||
|
||||
|
||||
def render_icon(icon: Icon, ports: dict[PortID, Port], size: QSize = DEFAULT_ICON_SIZE, render_ports: bool = False) -> QIcon:
|
||||
pixmap = QPixmap(size)
|
||||
pixmap.fill(Qt.GlobalColor.transparent)
|
||||
bounds = get_bounding_box(icon)
|
||||
if not icon.shapes and not icon.port_positions:
|
||||
return QIcon(pixmap)
|
||||
|
||||
available_width = max(1, size.width() - 4)
|
||||
available_height = max(1, size.height() - 4)
|
||||
scale = min(available_width / max(1, bounds.width()), available_height / max(1, bounds.height()))
|
||||
painter = QPainter(pixmap)
|
||||
painter.setRenderHint(QPainter.RenderHint.Antialiasing)
|
||||
painter.translate(size.width() / 2, size.height() / 2)
|
||||
painter.scale(scale, scale)
|
||||
painter.translate(-bounds.center())
|
||||
|
||||
for shape in sorted(icon.shapes.values(), key=lambda item: item.layer):
|
||||
if isinstance(shape, Rectangle):
|
||||
painter.setPen(_line_pen(shape.line_type, shape.line_thickness, shape.line_color))
|
||||
painter.setBrush(QBrush(_color(shape.fill_color)))
|
||||
painter.drawRoundedRect(QRectF(shape.pos[0], shape.pos[1], shape.width, shape.height), shape.corner_radius, shape.corner_radius)
|
||||
elif isinstance(shape, Text):
|
||||
font = QFont()
|
||||
font.setPixelSize(max(1, round(shape.size)))
|
||||
font.setBold(shape.bold)
|
||||
font.setItalic(shape.italic)
|
||||
painter.setFont(font)
|
||||
painter.setPen(_color(shape.color))
|
||||
painter.drawText(QRectF(shape.pos[0], shape.pos[1], shape.width, shape.height), Qt.AlignmentFlag.AlignCenter | Qt.TextFlag.TextWordWrap, shape.text)
|
||||
elif isinstance(shape, Line):
|
||||
painter.setPen(_line_pen(shape.line_type, shape.line_thickness, shape.line_color))
|
||||
painter.drawLine(shape.pos[0], shape.pos[1], shape.end[0], shape.end[1])
|
||||
|
||||
if render_ports:
|
||||
painter.setPen(QPen(QColor("#000000")))
|
||||
for port_id, position in icon.port_positions.items():
|
||||
port = ports.get(port_id)
|
||||
if port is None:
|
||||
continue
|
||||
color = QColor("#000000") if port.direction is SignalDirection.INPUT else QColor("#ffffff")
|
||||
painter.setBrush(QBrush(color))
|
||||
painter.drawRect(position[0], position[1], PORT_SIZE, PORT_SIZE)
|
||||
|
||||
painter.end()
|
||||
return QIcon(pixmap)
|
||||
|
||||
|
||||
def _line_pen(line_type: LineType, thickness: float, color: str) -> QPen:
|
||||
styles = {LineType.SOLID: Qt.PenStyle.SolidLine, LineType.DASHED: Qt.PenStyle.DashLine, LineType.DOTTED: Qt.PenStyle.DotLine, LineType.DASH_DOT: Qt.PenStyle.DashDotLine}
|
||||
if line_type is LineType.NONE:
|
||||
return QPen(Qt.PenStyle.NoPen)
|
||||
return QPen(_color(color), thickness, styles[line_type])
|
||||
|
||||
|
||||
def _color(value: str) -> QColor:
|
||||
color = value.removeprefix("#")
|
||||
if len(color) == 8:
|
||||
return QColor(int(color[0:2], 16), int(color[2:4], 16), int(color[4:6], 16), int(color[6:8], 16))
|
||||
return QColor(value)
|
||||
|
||||
Reference in New Issue
Block a user