Source code for ironflow.gui.workflows.canvas_widgets.ports

# coding: utf-8
# Copyright (c) Max-Planck-Institut für Eisenforschung GmbH - Computational Materials Design (CM) Department
# Distributed under the terms of "New BSD License", see the LICENSE file.
"""
Canvas widgets for ryven IO ports.
"""

from __future__ import annotations

from typing import TYPE_CHECKING, Literal, Optional

from ironflow.gui.workflows.canvas_widgets.base import HideableWidget, CanvasWidget
from ironflow.gui.workflows.canvas_widgets.layouts import PortLayout

if TYPE_CHECKING:
    from ironflow.gui.workflows.canvas_widgets.flow import FlowCanvas
    from ironflow.gui.workflows.canvas_widgets.base import Number
    from ironflow.model.port import NodeInput, NodeOutput


[docs] class PortWidget(HideableWidget): def __init__( self, x: Number, y: Number, parent: FlowCanvas | CanvasWidget, layout: PortLayout, port: NodeInput | NodeOutput, selected: bool = False, title: Optional[str] = None, hidden_x: Optional[Number] = None, hidden_y: Optional[Number] = None, radius: Number = 10, title_alignment: Literal["start", "end"] = "start", ): super().__init__( x=x, y=y, parent=parent, layout=layout, selected=selected, title=title if title is not None else port.label_str, hidden_x=hidden_x, hidden_y=hidden_y, ) self.radius = radius self.port = port self.title_alignment = title_alignment self.highlighted = False
[docs] def on_click( self, last_selected_object: Optional[CanvasWidget] ) -> PortWidget | None: if last_selected_object == self: self.deselect() return None elif isinstance(last_selected_object, PortWidget): self.flow.connect_nodes(last_selected_object.port, self.port) self.deselect_all() return None else: if last_selected_object is not None: last_selected_object.deselect() self.select() return self
@property def _current_color(self): if self.highlighted: color = self.layout.highlight_color elif self.port.ready: if self.selected: color = self.layout.valid_selected_color else: color = self.layout.valid_color else: if self.selected: color = self.layout.invalid_selected_color else: color = self.layout.invalid_color return color
[docs] def draw_shape(self) -> None: self.canvas.fill_style = self._current_color self.canvas.fill_circle(self.x, self.y, self.radius)
[docs] def draw_title(self) -> None: self.canvas.font = self.layout.font_string self.canvas.fill_style = self.layout.font_color shift_magnitude = self.radius + 3 if self.title_alignment == "start": shift = shift_magnitude elif self.title_alignment == "end": shift = -shift_magnitude else: raise ValueError( f"Title alignment {self.title_alignment} not recognized, please choose start or end" ) self.canvas.text_align = self.title_alignment title = self.title.upper() if self.port.dtype.batched else self.title self.canvas.fill_text( title[: self.layout.max_title_chars], self.x + shift, self.y + self.radius // 2, ) self.canvas.text_align = "start" # Revert to default after writing
def _is_at_xy(self, x_in: Number, y_in: Number) -> bool: return (x_in - self.x) ** 2 + (y_in - self.y) ** 2 < self.radius**2
[docs] def select(self) -> None: super().select() self.gui.build_recommendations(self.port) self.flow_canvas.highlight_compatible_ports(self)
[docs] def deselect(self) -> None: super().deselect() self.flow_canvas.clear_port_highlighting()
[docs] def highlight(self): self.highlighted = True
[docs] def dehighlight(self): self.highlighted = False