<commit_before>from __future__ import annotations

import ast
from dataclasses import replace
from math import atan2

import gaphas
from gaphas.aspect.connector import ConnectionSink
from gaphas.aspect.connector import Connector as ConnectorAspect
from gaphas.connector import Handle
from gaphas.geometry import Rectangle, distance_rectangle_point
from gaphas.solver.constraint import BaseConstraint

from gaphor.core.modeling.diagram import Diagram
from gaphor.core.modeling.event import RevertibeEvent
from gaphor.core.modeling.presentation import Presentation, S
from gaphor.core.modeling.properties import attribute
from gaphor.core.styling import Style, merge_styles
from gaphor.diagram.text import TextAlign, text_point_at_line


class Named:
    """Marker for any NamedElement presentations."""


class Classified(Named):
    """Marker for Classifier presentations."""


def from_package_str(item):
    """Display name space info when it is different, then diagram's or parent's
    namespace."""
    subject = item.subject
    diagram = item.diagram

    if not (subject and diagram):
        return False

    namespace = subject.namespace
    parent = item.parent

    # if there is a parent (i.e. interaction)
    if parent and parent.subject and parent.subject.namespace is not namespace:
        return False

    return f"(from {namespace.name})" if namespace is not item.diagram.namespace else ""


def postload_connect(item: gaphas.Item, handle: gaphas.Handle, target: gaphas.Item):
    """Helper function: when loading a model, handles should be connected as
    part of the `postload` step.

    This function finds a suitable spot on the `target` item to connect
    the handle to.
    """
    connector = ConnectorAspect(item, handle, item.diagram.connections)
    sink = ConnectionSink(target, distance=1e4)
    connector.connect(sink)


class HandlePositionEvent(RevertibeEvent):

    requires_transaction = False

    def __init__(self, element, index, old_value):
        super().__init__(element)
        self.index = index
        self.old_value = old_value

    def revert(self, target):
        target.handles()[self.index].pos = self.old_value
        target.request_update()


class HandlePositionUpdate:
    def watch_handle(self, handle):
        handle.pos.add_handler(self._on_handle_position_update)

    def remove_watch_handle(self, handle):
        handle.pos.remove_handler(self._on_handle_position_update)

    def _on_handle_position_update(self, position, old):
        for index, handle in enumerate(self.handles()):  # type: ignore[attr-defined]
            if handle.pos is position:
                break
        else:
            return
        self.handle(HandlePositionEvent(self, index, old))  # type: ignore[attr-defined]


# Note: the official documentation is using the terms "Shape" and "Edge" for element and line.


class ElementPresentation(gaphas.Element, HandlePositionUpdate, Presentation[S]):
    """Presentation for Gaphas Element (box-like) items.

    To create a shape (boxes, text), assign a shape to `self.shape`. If
    the shape can change, for example, because styling needs to change,
    implement the method `update_shapes()` and set self.shape there.
    """

    width: int
    height: int

    _port_sides = ("top", "right", "bottom", "left")

    def __init__(self, diagram: Diagram, id=None, shape=None, width=100, height=50):
        super().__init__(connections=diagram.connections, diagram=diagram, id=id, width=width, height=height)  # type: ignore[call-arg]
        self._shape = shape
        for handle in self.handles():
            self.watch_handle(handle)

        diagram.connections.add_constraint(
            self, MinimalValueConstraint(self.min_width, width)
        )
        diagram.connections.add_constraint(<commit_msg>Remove unneeded types<commit_after>from __future__ import annotations

import ast
from dataclasses import replace
from math import atan2

import gaphas
from gaphas.aspect.connector import ConnectionSink
from gaphas.aspect.connector import Connector as ConnectorAspect
from gaphas.connector import Handle
from gaphas.geometry import Rectangle, distance_rectangle_point
from gaphas.solver.constraint import BaseConstraint

from gaphor.core.modeling.diagram import Diagram
from gaphor.core.modeling.event import RevertibeEvent
from gaphor.core.modeling.presentation import Presentation, S
from gaphor.core.modeling.properties import attribute
from gaphor.core.styling import Style, merge_styles
from gaphor.diagram.text import TextAlign, text_point_at_line


class Named:
    """Marker for any NamedElement presentations."""


class Classified(Named):
    """Marker for Classifier presentations."""


def from_package_str(item):
    """Display name space info when it is different, then diagram's or parent's
    namespace."""
    subject = item.subject
    diagram = item.diagram

    if not (subject and diagram):
        return False

    namespace = subject.namespace
    parent = item.parent

    # if there is a parent (i.e. interaction)
    if parent and parent.subject and parent.subject.namespace is not namespace:
        return False

    return f"(from {namespace.name})" if namespace is not item.diagram.namespace else ""


def postload_connect(item: gaphas.Item, handle: gaphas.Handle, target: gaphas.Item):
    """Helper function: when loading a model, handles should be connected as
    part of the `postload` step.

    This function finds a suitable spot on the `target` item to connect
    the handle to.
    """
    connector = ConnectorAspect(item, handle, item.diagram.connections)
    sink = ConnectionSink(target, distance=1e4)
    connector.connect(sink)


class HandlePositionEvent(RevertibeEvent):

    requires_transaction = False

    def __init__(self, element, index, old_value):
        super().__init__(element)
        self.index = index
        self.old_value = old_value

    def revert(self, target):
        target.handles()[self.index].pos = self.old_value
        target.request_update()


class HandlePositionUpdate:
    def watch_handle(self, handle):
        handle.pos.add_handler(self._on_handle_position_update)

    def remove_watch_handle(self, handle):
        handle.pos.remove_handler(self._on_handle_position_update)

    def _on_handle_position_update(self, position, old):
        for index, handle in enumerate(self.handles()):  # type: ignore[attr-defined]
            if handle.pos is position:
                break
        else:
            return
        self.handle(HandlePositionEvent(self, index, old))  # type: ignore[attr-defined]


# Note: the official documentation is using the terms "Shape" and "Edge" for element and line.


class ElementPresentation(gaphas.Element, HandlePositionUpdate, Presentation[S]):
    """Presentation for Gaphas Element (box-like) items.

    To create a shape (boxes, text), assign a shape to `self.shape`. If
    the shape can change, for example, because styling needs to change,
    implement the method `update_shapes()` and set self.shape there.
    """

    _port_sides = ("top", "right", "bottom", "left")

    def __init__(self, diagram: Diagram, id=None, shape=None, width=100, height=50):
        super().__init__(connections=diagram.connections, diagram=diagram, id=id, width=width, height=height)  # type: ignore[call-arg]
        self._shape = shape
        for handle in self.handles():
            self.watch_handle(handle)

        diagram.connections.add_constraint(
            self, MinimalValueConstraint(self.min_width, width)
        )
        diagram.connections.add_constraint(
{'fraction_non_alphanumeric': 0.08668242710795902, 'fraction_numerical': 0.0021013921723141583, 'mean_word_length': 3.689039408866995, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1338355', 'n_tokens_mistral': 2182, 'n_tokens_neox': 2082, 'n_words': 651}