wiRedPanda
Logic Circuit Simulator
Loading...
Searching...
No Matches
ElementOrientation.cpp
Go to the documentation of this file.
1// Copyright 2015 - 2026, GIBIS-UNIFESP and the wiRedPanda contributors
2// SPDX-License-Identifier: GPL-3.0-or-later
3
5
6#include <cmath>
7
9#include "App/Wiring/Port.h"
10
12{
13 // Keep angle in [0, 360) to avoid accumulated floating-point drift across many rotations
14 m_angle = std::fmod(angle, 360);
15 // Rotatable elements rotate the entire QGraphicsItem (pixmap + ports move together), then
16 // swap in a pixmap whose baked-in SVG <text> is counter-rotated so the labels stay upright.
17 // Non-rotatable elements (inputs/outputs) keep the pixmap fixed and only spin ports
18 // around the element centre so connections track the correct positions.
19 if (m_owner->rotatesGraphic()) {
20 m_owner->QGraphicsItem::setRotation(m_angle);
21 m_owner->reapplyAppearanceOrientation();
22 } else {
24 }
25}
26
28{
29 for (auto *port : m_owner->allPorts()) {
30 orientPort(port);
31 }
32}
33
35{
36 // Non-rotatable elements keep their pixmap fixed and instead transform each port about the
37 // pixmap centre, so the port moves to the rotated/mirrored side while the graphic stays
38 // upright. The single combined transform encodes both rotation and the flip flags, so all
39 // three triggers (updatePortsProperties, setRotation, setFlippedX/Y) produce the same result.
40 port->setRotation(0);
41 port->setTransformOriginPoint(QPointF());
42
43 // pixmapCenter() expressed in the port's local frame. port->pos() is the port's base
44 // position — flip and rotation use the transform and never move pos — so this is stable
45 // and independent of any transform already on the port (keeps the operation involutive).
46 const QPointF origin = m_owner->pixmapCenter() - port->pos();
47
48 QTransform t;
49 t.translate(origin.x(), origin.y());
50 t.rotate(m_angle);
51 t.scale(m_flippedX ? -1 : 1, m_flippedY ? -1 : 1);
52 t.translate(-origin.x(), -origin.y());
53 port->setTransform(t);
54
55 port->updateConnections();
56}
57
58void ElementOrientation::setFlippedX(const bool flipped)
59{
60 m_flippedX = flipped;
61 applyFlipTransform();
62}
63
64void ElementOrientation::setFlippedY(const bool flipped)
65{
66 m_flippedY = flipped;
67 applyFlipTransform();
68}
69
70void ElementOrientation::applyFlipTransform()
71{
72 // Non-rotatable elements (inputs/outputs) keep their pixmap fixed and mirror only their
73 // ports — exactly as rotation does for them — so a flipped pushbutton/display never renders
74 // its graphic reversed. rotatePorts() re-applies the combined rotation+flip orientation.
75 if (!m_owner->rotatesGraphic()) {
77 return;
78 }
79
80 if (!m_flippedX && !m_flippedY) {
81 m_owner->setTransform(QTransform());
82 } else {
83 const auto center = m_owner->pixmapCenter();
84 QTransform t;
85 t.translate(center.x(), center.y());
86 t.scale(m_flippedX ? -1 : 1, m_flippedY ? -1 : 1);
87 t.translate(-center.x(), -center.y());
88 m_owner->setTransform(t);
89 }
90
91 // The item transform above mirrors the whole pixmap (and moves the ports). Swap in a pixmap
92 // whose baked-in SVG <text> is pre-counter-oriented so the glyphs read upright after the
93 // rotation + flip while still moving to the opposite side. No-op for an upright, unflipped or
94 // non-SVG pixmap.
95 m_owner->reapplyAppearanceOrientation();
96 m_owner->update();
97}
Owns a GraphicElement's rotation angle and flip (mirror) state.
Abstract base class for all graphical circuit elements.
Port classes: Port (base), InputPort, and OutputPort.
void orientPort(Port *port)
Orients port for the current rotation + flip state.
void setFlippedX(bool flipped)
Sets the horizontal mirror state and updates the item transform.
void setFlippedY(bool flipped)
Sets the vertical mirror state and updates the item transform.
void setRotation(qreal angle)
Rotates to angle degrees (normalised to [0, 360)) and updates port positions.
qreal angle() const
Returns the current rotation angle in degrees.
bool rotatesGraphic() const
Abstract base class for circuit element ports (connection endpoints).
Definition Port.h:39
void updateConnections()
Triggers a path update on all attached connections.
Definition Port.cpp:100