diff --git a/b_asic/GUI/_preferences.py b/b_asic/GUI/_preferences.py index c1fa14062d99ec3480ae1bd114c185f470fca202..8ec13464dfbe6742f22f147168bb0255db9f227b 100644 --- a/b_asic/GUI/_preferences.py +++ b/b_asic/GUI/_preferences.py @@ -14,3 +14,4 @@ MIN_HEIGHT_SCENE = 520 # Interface LINECOLOR = QColor(*SIGNAL_COLOR) +GRID = 19 diff --git a/b_asic/GUI/arrow.py b/b_asic/GUI/arrow.py index 66805a432ce970ae2852f965d587bb760e8de1c1..1c3fcce263082213a81e6c6893c3852c347c4123 100644 --- a/b_asic/GUI/arrow.py +++ b/b_asic/GUI/arrow.py @@ -1,12 +1,12 @@ from qtpy.QtCore import QPointF -from qtpy.QtGui import QPen, QPolygonF -from qtpy.QtWidgets import QGraphicsPolygonItem, QMenu +from qtpy.QtGui import QPen, QPainterPath +from qtpy.QtWidgets import QGraphicsPathItem, QMenu from b_asic.GUI._preferences import LINECOLOR, PORTHEIGHT, PORTWIDTH from b_asic.signal import Signal -class Arrow(QGraphicsPolygonItem): +class Arrow(QGraphicsPathItem): """Arrow/connection in signal flow graph GUI.""" def __init__(self, source, destination, window, signal=None, parent=None): @@ -80,10 +80,29 @@ class Arrow(QGraphicsPolygonItem): """ Draw a line connecting self.source with self.destination. Used as callback when moving operations. """ + ORTHOGONAL = True + OFFSET = 2 * PORTWIDTH self.setPen(QPen(LINECOLOR, 3)) x0 = self.source.operation.x() + self.source.x() + PORTWIDTH - y0 = self.source.operation.y() + self.source.y() + PORTHEIGHT/2 + y0 = self.source.operation.y() + self.source.y() + PORTHEIGHT / 2 x1 = self.destination.operation.x() + self.destination.x() - y1 = self.destination.operation.y() + self.destination.y() + PORTHEIGHT/2 - p = QPolygonF() << QPointF(x0, y0) << QPointF(x1, y1) - self.setPolygon(p) + y1 = ( + self.destination.operation.y() + + self.destination.y() + + PORTHEIGHT / 2 + ) + xmid = (x0 + x1) / 2 + ymid = (y0 + y1) / 2 + p = QPainterPath(QPointF(x0, y0)) + if y0 == y1 or not ORTHOGONAL: + pass + elif abs(x0 - x1) <= OFFSET / 2: + p.lineTo(QPointF(x0 + OFFSET, y0)) + p.lineTo(QPointF(x0 + OFFSET, ymid)) + p.lineTo(QPointF(x0 - OFFSET, ymid)) + p.lineTo(QPointF(x0 - OFFSET, y1)) + else: + p.lineTo(QPointF(xmid, y0)) + p.lineTo(QPointF(xmid, y1)) + p.lineTo(QPointF(x1, y1)) + self.setPath(p) diff --git a/b_asic/GUI/drag_button.py b/b_asic/GUI/drag_button.py index 3b258c621ca0983fbc9e1c83aefac042be147232..79a03c9a37244cfe1cae63dfb62601eb66902fa6 100644 --- a/b_asic/GUI/drag_button.py +++ b/b_asic/GUI/drag_button.py @@ -12,7 +12,7 @@ from qtpy.QtWidgets import QAction, QMenu, QPushButton from b_asic.GUI.properties_window import PropertiesWindow from b_asic.GUI.utils import decorate_class, handle_error -from b_asic.GUI._preferences import MINBUTTONSIZE +from b_asic.GUI._preferences import GRID, MINBUTTONSIZE @decorate_class(handle_error) @@ -105,6 +105,15 @@ class DragButton(QPushButton): else: self.select_button(event.modifiers()) + # Snap + point = self.pos() + x = point.x() + y = point.y() + newx = GRID * round(x / GRID) + newy = GRID * round(y / GRID) + self.move(newx, newy) + self._window.scene.update() + self._window.graphic_view.update() super().mouseReleaseEvent(event) def _toggle_button(self, pressed=False): @@ -117,7 +126,9 @@ class DragButton(QPushButton): path_to_image = os.path.join( os.path.dirname(__file__), "operation_icons", - f"{self.operation_path_name}{'_grey.png' if self.pressed else '.png'}", + ( + f"{self.operation_path_name}{'_grey.png' if self.pressed else '.png'}" + ), ) self.setIcon(QIcon(path_to_image)) self.setIconSize(QSize(MINBUTTONSIZE, MINBUTTONSIZE)) diff --git a/b_asic/GUI/main_window.py b/b_asic/GUI/main_window.py index ac0ecb687f98d310a32c23ea3de22742abb4623d..a7d6ee88d639fec2e1cf4514c07dd32e3d04aff4 100644 --- a/b_asic/GUI/main_window.py +++ b/b_asic/GUI/main_window.py @@ -37,6 +37,7 @@ from b_asic.GUI.port_button import PortButton from b_asic.GUI.select_sfg_window import SelectSFGWindow from b_asic.GUI._preferences import ( GAP, + GRID, MINBUTTONSIZE, PORTHEIGHT, PORTWIDTH, @@ -540,7 +541,7 @@ class MainWindow(QMainWindow): op.graph_id, op, op.type_name().lower(), True, window=self ) if position is None: - attr_button.move(250, 100) + attr_button.move(GRID * 3, GRID * 2) else: attr_button.move(*position)