fix some things
This commit is contained in:
@@ -53,14 +53,14 @@ class Icon:
|
||||
if not self.elements:
|
||||
self.elements = [{
|
||||
"type": "ellipse" if self.shape == "ellipse" else "rectangle",
|
||||
"x": 1.0, "y": 1.0, "width": self.width - 2.0, "height": self.height - 2.0,
|
||||
"x": 32.0, "y": 32.0, "width": 64.0, "height": 64.0,
|
||||
"fill": self.fill, "stroke": self.border, "lineWidth": 1.5,
|
||||
"lineStyle": "solid", "cornerRadius": 5.0,
|
||||
}]
|
||||
if self.text:
|
||||
self.elements.append({
|
||||
"type": "text", "x": 8.0, "y": 8.0,
|
||||
"width": self.width - 16.0, "height": self.height - 16.0,
|
||||
"type": "text", "x": 40.0, "y": 40.0,
|
||||
"width": 48.0, "height": 48.0,
|
||||
"text": self.text, "color": "#202020", "fontSize": 12.0,
|
||||
})
|
||||
|
||||
|
||||
@@ -4,6 +4,22 @@ from PySide6.QtGui import QColor, QFont, QIcon, QPainter, QPen, QPixmap, QPolygo
|
||||
from bedit.document.model import Icon
|
||||
|
||||
|
||||
def icon_bounds(icon: Icon) -> QRectF:
|
||||
"""Return the automatic hitbox of all visible vector elements."""
|
||||
bounds = QRectF()
|
||||
for element in icon.elements:
|
||||
if element.get("_deleted"):
|
||||
continue
|
||||
rect = QRectF(
|
||||
float(element.get("x", 0)),
|
||||
float(element.get("y", 0)),
|
||||
max(0.0, float(element.get("width", 0))),
|
||||
max(0.0, float(element.get("height", 0))),
|
||||
)
|
||||
bounds = rect if bounds.isNull() else bounds.united(rect)
|
||||
return bounds if not bounds.isNull() else QRectF(32, 32, 64, 64)
|
||||
|
||||
|
||||
def _pen(element: dict) -> QPen:
|
||||
styles = {
|
||||
"solid": Qt.PenStyle.SolidLine,
|
||||
@@ -19,11 +35,19 @@ def _pen(element: dict) -> QPen:
|
||||
)
|
||||
|
||||
|
||||
def paint_icon(painter: QPainter, icon: Icon, target: QRectF) -> None:
|
||||
def paint_icon(
|
||||
painter: QPainter,
|
||||
icon: Icon,
|
||||
target: QRectF,
|
||||
source: QRectF | None = None,
|
||||
) -> None:
|
||||
painter.save()
|
||||
painter.setRenderHint(QPainter.RenderHint.Antialiasing)
|
||||
if source is None:
|
||||
source = QRectF(0, 0, icon.width, icon.height)
|
||||
painter.translate(target.topLeft())
|
||||
painter.scale(target.width() / icon.width, target.height() / icon.height)
|
||||
painter.scale(target.width() / source.width(), target.height() / source.height())
|
||||
painter.translate(-source.left(), -source.top())
|
||||
for element in icon.elements:
|
||||
kind = element.get("type", "rectangle")
|
||||
rect = QRectF(
|
||||
@@ -55,12 +79,20 @@ def icon_pixmap(icon: Icon, size: int = 16) -> QPixmap:
|
||||
pixmap = QPixmap(size, size)
|
||||
pixmap.fill(Qt.GlobalColor.transparent)
|
||||
painter = QPainter(pixmap)
|
||||
ratio = min(size / icon.width, size / icon.height)
|
||||
width, height = icon.width * ratio, icon.height * ratio
|
||||
paint_icon(painter, icon, QRectF((size - width) / 2, (size - height) / 2, width, height))
|
||||
bounds = icon_bounds(icon)
|
||||
ratio = min(size / bounds.width(), size / bounds.height())
|
||||
width, height = bounds.width() * ratio, bounds.height() * ratio
|
||||
paint_icon(
|
||||
painter,
|
||||
icon,
|
||||
QRectF((size - width) / 2, (size - height) / 2, width, height),
|
||||
bounds,
|
||||
)
|
||||
painter.end()
|
||||
return pixmap
|
||||
|
||||
|
||||
def library_icon(icon: Icon) -> QIcon:
|
||||
return QIcon(icon_pixmap(icon, 16))
|
||||
# Render large enough for the tall Libraries rows. icon_pixmap crops to the
|
||||
# vector hitbox first, so a 32x32 drawing is shown as large as a 128x128 one.
|
||||
return QIcon(icon_pixmap(icon, 28))
|
||||
|
||||
@@ -31,6 +31,10 @@ class MainWindow(QMainWindow):
|
||||
super().__init__()
|
||||
self.ui = Ui_MainWindow()
|
||||
self.ui.setupUi(self)
|
||||
self.ui.emptyPage.setStyleSheet("background-color: #9a9a9a;")
|
||||
self.ui.emptyWorkspaceLabel.setStyleSheet(
|
||||
"background: transparent; color: #202020;"
|
||||
)
|
||||
self._create_camera_toolbar()
|
||||
self.settings = QSettings()
|
||||
|
||||
@@ -63,7 +67,8 @@ class MainWindow(QMainWindow):
|
||||
|
||||
def _configure_models(self) -> None:
|
||||
self.ui.treeView.setModel(self.library_tree_model)
|
||||
self.ui.treeView.setIconSize(QSize(16, 16))
|
||||
self.ui.treeView.setIconSize(QSize(28, 28))
|
||||
self.ui.treeView.setStyleSheet("QTreeView::item { height: 32px; }")
|
||||
self.ui.treeView.setHeaderHidden(True)
|
||||
self.ui.treeView.setDragEnabled(True)
|
||||
self.ui.treeView.setDragDropMode(self.ui.treeView.DragDropMode.DragOnly)
|
||||
@@ -379,6 +384,7 @@ class MainWindow(QMainWindow):
|
||||
scene = self.ui.graphView.scene()
|
||||
if scene is not None:
|
||||
scene.update()
|
||||
self.ui.graphView.viewport().update()
|
||||
|
||||
def _document_opened_changed(self, opened: bool) -> None:
|
||||
for action in (self.ui.actionClose, self.ui.actionSave, self.ui.actionSaveAs):
|
||||
|
||||
@@ -31,7 +31,7 @@ from PySide6.QtWidgets import (
|
||||
from bedit.document.controller import DocumentController
|
||||
from bedit.document.model import Component, Connection, Endpoint, Port
|
||||
from bedit.library.tree_model import COMPONENT_MIME_TYPE
|
||||
from bedit.icon_renderer import paint_icon
|
||||
from bedit.icon_renderer import icon_bounds, paint_icon
|
||||
|
||||
|
||||
SELECTION_MIME_TYPE = "application/x-bedit-selection"
|
||||
@@ -67,6 +67,7 @@ class ComponentGraphicsItem(QGraphicsObject):
|
||||
self.component = component
|
||||
self.controller = controller
|
||||
self.drag_start = QPointF()
|
||||
self.hitbox = icon_bounds(component.icon)
|
||||
self.setFlags(
|
||||
QGraphicsItem.GraphicsItemFlag.ItemIsMovable
|
||||
| QGraphicsItem.GraphicsItemFlag.ItemIsSelectable
|
||||
@@ -74,7 +75,7 @@ class ComponentGraphicsItem(QGraphicsObject):
|
||||
)
|
||||
self.input_ports = self._create_ports(component.inputs, "target", 0.0)
|
||||
self.output_ports = self._create_ports(component.outputs, "source", self.WIDTH)
|
||||
self.setTransformOriginPoint(self.WIDTH / 2, self.HEIGHT / 2)
|
||||
self.setTransformOriginPoint(self.hitbox.center())
|
||||
self.setRotation(component.rotation)
|
||||
|
||||
def _create_ports(self, ports, role: str, x: float) -> dict[str, ConnectionPortItem]:
|
||||
@@ -92,7 +93,7 @@ class ComponentGraphicsItem(QGraphicsObject):
|
||||
return result
|
||||
|
||||
def boundingRect(self) -> QRectF: # noqa: N802
|
||||
return QRectF(0, 0, self.WIDTH, self.HEIGHT)
|
||||
return self.hitbox
|
||||
|
||||
def paint(
|
||||
self,
|
||||
@@ -101,7 +102,11 @@ class ComponentGraphicsItem(QGraphicsObject):
|
||||
widget: QWidget | None = None,
|
||||
) -> None:
|
||||
del option, widget
|
||||
paint_icon(painter, self.component.icon, self.boundingRect())
|
||||
paint_icon(
|
||||
painter,
|
||||
self.component.icon,
|
||||
QRectF(0, 0, self.WIDTH, self.HEIGHT),
|
||||
)
|
||||
if self.isSelected():
|
||||
painter.setBrush(Qt.BrushStyle.NoBrush)
|
||||
painter.setPen(QPen(QColor("#2563eb"), 2, Qt.PenStyle.DashLine))
|
||||
@@ -333,17 +338,8 @@ class GraphScene(QGraphicsScene):
|
||||
self.update_connection(connection.id)
|
||||
|
||||
def drawBackground(self, painter: QPainter, rect: QRectF) -> None: # noqa: N802
|
||||
painter.fillRect(rect, QColor("#e4e4e4"))
|
||||
if self.controller.document is None or self.controller.active_component is None:
|
||||
return
|
||||
spacing = _graph_grid_size()
|
||||
left = int(rect.left()) - (int(rect.left()) % spacing)
|
||||
top = int(rect.top()) - (int(rect.top()) % spacing)
|
||||
painter.setPen(QPen(QColor("#b9c0c7"), 0))
|
||||
for x in range(left, int(rect.right()) + spacing, spacing):
|
||||
painter.drawLine(x, rect.top(), x, rect.bottom())
|
||||
for y in range(top, int(rect.bottom()) + spacing, spacing):
|
||||
painter.drawLine(rect.left(), y, rect.right(), y)
|
||||
# The view paints the grid so it always covers the complete viewport.
|
||||
del painter, rect
|
||||
|
||||
def _endpoint_item(self, endpoint: Endpoint, role: str) -> ConnectionPortItem | None:
|
||||
if endpoint.interface is not None:
|
||||
@@ -412,10 +408,28 @@ class GraphWorkspaceView(QGraphicsView):
|
||||
self.setAcceptDrops(True)
|
||||
self.setRenderHint(QPainter.RenderHint.Antialiasing)
|
||||
self.setDragMode(QGraphicsView.DragMode.RubberBandDrag)
|
||||
self.setBackgroundBrush(QColor("#9a9a9a"))
|
||||
self.setBackgroundBrush(QColor("#f7f7f7"))
|
||||
self.setTransformationAnchor(QGraphicsView.ViewportAnchor.AnchorUnderMouse)
|
||||
self.setResizeAnchor(QGraphicsView.ViewportAnchor.AnchorViewCenter)
|
||||
|
||||
def drawBackground(self, painter: QPainter, rect: QRectF) -> None: # noqa: N802
|
||||
"""Paint the visible graph viewport in scene coordinates."""
|
||||
painter.fillRect(rect, QColor("#f7f7f7"))
|
||||
if (
|
||||
self.controller is None
|
||||
or self.controller.document is None
|
||||
or self.controller.active_component is None
|
||||
):
|
||||
return
|
||||
spacing = _graph_grid_size()
|
||||
left = int(rect.left()) - (int(rect.left()) % spacing)
|
||||
top = int(rect.top()) - (int(rect.top()) % spacing)
|
||||
painter.setPen(QPen(QColor("#c5cbd1"), 0))
|
||||
for x in range(left, int(rect.right()) + spacing, spacing):
|
||||
painter.drawLine(QPointF(x, rect.top()), QPointF(x, rect.bottom()))
|
||||
for y in range(top, int(rect.bottom()) + spacing, spacing):
|
||||
painter.drawLine(QPointF(rect.left(), y), QPointF(rect.right(), y))
|
||||
|
||||
def _zoom(self, factor: float) -> None:
|
||||
current = self.transform().m11()
|
||||
target = current * factor
|
||||
|
||||
Reference in New Issue
Block a user