wiRedPanda
Logic Circuit Simulator
Loading...
Searching...
No Matches
Display16.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 <QPainter>
7#include <QSvgRenderer>
8
14#include "App/IO/VersionInfo.h"
15#include "App/Wiring/Port.h"
16
17template<>
20 .type = ElementType::Display16,
21 .group = ElementGroup::Output,
22 .minInputSize = 17,
23 .maxInputSize = 17,
24 .canChangeAppearance = true,
25 .hasColors = true,
26 .hasLabel = true,
27 .rotatesGraphic = false,
28 };
29 static_assert(validate(constraints));
30
32 {
34 meta.pixmapPath = []{ return QStringLiteral(":/Components/Output/Counter/counter_16_on.svg"); };
35 meta.titleText = QT_TRANSLATE_NOOP("Display16", "16-SEGMENT DISPLAY");
36 meta.translatedName = QT_TRANSLATE_NOOP("Display16", "16-Segment Display");
37 meta.trContext = "Display16";
38 meta.defaultAppearances = QStringList({
39 ":/Components/Output/Counter/counter_16_off.svg",
40 ":/Components/Output/Counter/counter_a1.svg",
41 ":/Components/Output/Counter/counter_a2.svg",
42 ":/Components/Output/Counter/counter_b.svg",
43 ":/Components/Output/Counter/counter_c.svg",
44 ":/Components/Output/Counter/counter_d1.svg",
45 ":/Components/Output/Counter/counter_d2.svg",
46 ":/Components/Output/Counter/counter_e.svg",
47 ":/Components/Output/Counter/counter_f.svg",
48 ":/Components/Output/Counter/counter_g1.svg",
49 ":/Components/Output/Counter/counter_g2.svg",
50 ":/Components/Output/Counter/counter_h.svg",
51 ":/Components/Output/Counter/counter_j.svg",
52 ":/Components/Output/Counter/counter_k.svg",
53 ":/Components/Output/Counter/counter_l.svg",
54 ":/Components/Output/Counter/counter_m.svg",
55 ":/Components/Output/Counter/counter_n.svg",
56 ":/Components/Output/Counter/counter_dp.svg",
57 });
58 return meta;
59 }
60
61 static inline const bool registered = []() {
63 ElementFactory::registerCreator(constraints.type, [] { return new Display16(); });
64 return true;
65 }();
66};
67
68Display16::Display16(QGraphicsItem *parent)
70{
71 a1 = Display7::cachedSegmentRenderers(m_appearance.defaultAppearances().at(1));
72 a2 = Display7::cachedSegmentRenderers(m_appearance.defaultAppearances().at(2));
73 b = Display7::cachedSegmentRenderers(m_appearance.defaultAppearances().at(3));
74 c = Display7::cachedSegmentRenderers(m_appearance.defaultAppearances().at(4));
75 d1 = Display7::cachedSegmentRenderers(m_appearance.defaultAppearances().at(5));
76 d2 = Display7::cachedSegmentRenderers(m_appearance.defaultAppearances().at(6));
77 e = Display7::cachedSegmentRenderers(m_appearance.defaultAppearances().at(7));
78 f = Display7::cachedSegmentRenderers(m_appearance.defaultAppearances().at(8));
79 g1 = Display7::cachedSegmentRenderers(m_appearance.defaultAppearances().at(9));
80 g2 = Display7::cachedSegmentRenderers(m_appearance.defaultAppearances().at(10));
81 h = Display7::cachedSegmentRenderers(m_appearance.defaultAppearances().at(11));
82 j = Display7::cachedSegmentRenderers(m_appearance.defaultAppearances().at(12));
83 k = Display7::cachedSegmentRenderers(m_appearance.defaultAppearances().at(13));
84 l = Display7::cachedSegmentRenderers(m_appearance.defaultAppearances().at(14));
85 m = Display7::cachedSegmentRenderers(m_appearance.defaultAppearances().at(15));
86 n = Display7::cachedSegmentRenderers(m_appearance.defaultAppearances().at(16));
87 dp = Display7::cachedSegmentRenderers(m_appearance.defaultAppearances().at(17));
88
90}
91
93{
94 update();
95}
96
98{
99 // Ports on the left (x=0) drive left-side and center segments;
100 // ports on the right (x=64) drive right-side segments and DP.
101 // The port order follows the standard 16-segment naming convention
102 // (A1/A2 = top, B/C = right verticals, D1/D2 = bottom, E/F = left verticals,
103 // G1/G2 = middle, H/J/K/L/M/N = diagonals and center verticals).
104 inputPort( 0)->setPos( 0, -8); inputPort( 0)->setName("G1 (" + tr("middle left horizontal") + ")");
105 inputPort( 1)->setPos( 0, 8); inputPort( 1)->setName("F (" + tr("upper left vertical") + ")");
106 inputPort( 2)->setPos( 0, 24); inputPort( 2)->setName("E (" + tr("lower left vertical") + ")");
107 inputPort( 3)->setPos( 0, 40); inputPort( 3)->setName("D1 (" + tr("bottom left horizontal") + ")");
108 inputPort( 4)->setPos( 0, 56); inputPort( 4)->setName("D2 (" + tr("bottom right horizontal") + ")");
109 inputPort( 5)->setPos(64, -8); inputPort( 5)->setName("A1 (" + tr("top left horizontal") + ")");
110 inputPort( 6)->setPos(64, 8); inputPort( 6)->setName("A2 (" + tr("top right horizontal") + ")");
111 inputPort( 7)->setPos(64, 24); inputPort( 7)->setName("B (" + tr("upper right vertical") + ")");
112 inputPort( 8)->setPos(64, 40); inputPort( 8)->setName("DP (" + tr("dot") + ")");
113 inputPort( 9)->setPos(64, 56); inputPort( 9)->setName("C (" + tr("lower right vertical") + ")");
114 inputPort(10)->setPos( 0, 72); inputPort(10)->setName("G2 (" + tr("middle right horizontal") + ")");
115 inputPort(11)->setPos( 0, 88); inputPort(11)->setName("H (" + tr("upper left diagonal") + ")");
116 inputPort(12)->setPos( 0, 104); inputPort(12)->setName("J (" + tr("upper center vertical") + ")");
117 inputPort(13)->setPos(64, 72); inputPort(13)->setName("K (" + tr("upper right diagonal") + ")");
118 inputPort(14)->setPos(64, 88); inputPort(14)->setName("L (" + tr("lower right diagonal") + ")");
119 inputPort(15)->setPos(64, 104); inputPort(15)->setName("M (" + tr("lower center vertical") + ")");
120 inputPort(16)->setPos(64, 120); inputPort(16)->setName("N (" + tr("lower left diagonal") + ")");
121
122 for (auto *port : inputs()) {
123 port->setRequired(false);
124 port->setDefaultStatus(Status::Inactive);
125 }
126
127 // This override doesn't chain to the base updatePortsProperties(), so re-apply the current
128 // rotation/flip orientation to the freshly-positioned ports (keeps flip working on displays).
129 rotatePorts();
130}
131
132void Display16::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
133{
134 // Base class draws the off-state background; active segments are overlaid as vector
135 // renders on top, crisp at any zoom.
136 GraphicElement::paint(painter, option, widget);
137
138 const QRectF body(0, 0, 64, 64);
139 if (inputPort( 0)->status() == Status::Active) { g1.at(m_colorNumber)->render(painter, body); }
140 if (inputPort( 1)->status() == Status::Active) { f.at(m_colorNumber)->render(painter, body); }
141 if (inputPort( 2)->status() == Status::Active) { e.at(m_colorNumber)->render(painter, body); }
142 if (inputPort( 3)->status() == Status::Active) { d1.at(m_colorNumber)->render(painter, body); }
143 if (inputPort( 4)->status() == Status::Active) { d2.at(m_colorNumber)->render(painter, body); }
144 if (inputPort( 5)->status() == Status::Active) { a1.at(m_colorNumber)->render(painter, body); }
145 if (inputPort( 6)->status() == Status::Active) { a2.at(m_colorNumber)->render(painter, body); }
146 if (inputPort( 7)->status() == Status::Active) { b.at(m_colorNumber)->render(painter, body); }
147 if (inputPort( 8)->status() == Status::Active) { dp.at(m_colorNumber)->render(painter, body); }
148 if (inputPort( 9)->status() == Status::Active) { c.at(m_colorNumber)->render(painter, body); }
149 if (inputPort(10)->status() == Status::Active) { g2.at(m_colorNumber)->render(painter, body); }
150 if (inputPort(11)->status() == Status::Active) { h.at(m_colorNumber)->render(painter, body); }
151 if (inputPort(12)->status() == Status::Active) { j.at(m_colorNumber)->render(painter, body); }
152 if (inputPort(13)->status() == Status::Active) { k.at(m_colorNumber)->render(painter, body); }
153 if (inputPort(14)->status() == Status::Active) { l.at(m_colorNumber)->render(painter, body); }
154 if (inputPort(15)->status() == Status::Active) { m.at(m_colorNumber)->render(painter, body); }
155 if (inputPort(16)->status() == Status::Active) { n.at(m_colorNumber)->render(painter, body); }
156}
157
158void Display16::setColor(const QString &color)
159{
160 m_color = color;
161 m_colorNumber = colorNameToIndex(color);
162}
163
164QString Display16::color() const
165{
166 return m_color;
167}
168
169void Display16::save(QDataStream &stream, SerializationOptions options) const
170{
171 GraphicElement::save(stream, options);
172
173 QMap<QString, QVariant> map;
174 // PortableFile streams omit the default; fresh-loaded elements start there
175 // anyway. Snapshots write unconditionally (reloaded into live elements).
177 map.insert("color", color());
178 }
179
180 stream << map;
181}
182
183void Display16::load(QDataStream &stream, SerializationContext &context)
184{
185 GraphicElement::load(stream, context);
186
188 // v3.1–4.0 stored color as a bare QString
189 const QString color_ = Serialization::readBoundedString(stream);
190 setColor(color_);
191 }
192
193 if (VersionInfo::hasQMapFormat(context.version)) {
194 // v4.1+ uses a key-value map
195 QMap<QString, QVariant> map = Serialization::readBoundedMetadata(stream);
196
197 if (map.contains("color")) {
198 setColor(map.value("color").toString());
199 }
200 }
201}
Graphic element for the 16-segment LED display.
Graphic element for the 7-segment LED display.
Singleton factory for all circuit element types.
Self-registering element trait template and compile-time constraint validation.
ElementMetadata metadataFromConstraints(const ElementConstraints &c)
Converts ElementConstraints to an ElementMetadata with all constraint-derived fields set.
Definition ElementInfo.h:80
constexpr bool validate(const ElementConstraints &c)
Validates element constraints at compile time.
Definition ElementInfo.h:48
Enums::ElementType ElementType
Definition Enums.h:107
Port classes: Port (base), InputPort, and OutputPort.
Deserialization/serialization context structs passed through load()/save() call chains.
Circuit and waveform file serialization/deserialization utilities.
Named version predicates for file-format compatibility checks.
16-segment LED display output element (16 segments + decimal point = 17 inputs).
Definition Display16.h:24
void load(QDataStream &stream, SerializationContext &context) override
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override
void setColor(const QString &color) override
Sets the display color.
void refresh() override
Refreshes the displayed segments based on current input states.
Definition Display16.cpp:92
Display16(QGraphicsItem *parent=nullptr)
Constructs the element with optional parent.
Definition Display16.cpp:68
QString color() const override
Returns the current display color name.
static constexpr const char * kDefaultColor
Definition Display16.h:30
void updatePortsProperties() override
Updates port positions (fixed at 17 inputs).
Definition Display16.cpp:97
void save(QDataStream &stream, SerializationOptions options) const override
Serializes the color selection to stream.
static QVector< std::shared_ptr< QSvgRenderer > > cachedSegmentRenderers(const QString &resourcePath)
Definition Display7.cpp:94
static void registerCreator(ElementType type, std::function< GraphicElement *()> creator)
Registers a creator lambda for type, used by buildElement().
static void registerMetadata(const ElementMetadata &meta)
Registers meta in the global map (called once per element type at startup).
GraphicElement(ElementType type, QGraphicsItem *parent=nullptr)
Constructs a graphic element of the given type, fetching all properties from the metadata registry.
ElementAppearance m_appearance
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override
Paints the element onto the scene.
virtual void load(QDataStream &stream, SerializationContext &context)
Loads the graphic element through a binary data stream.
InputPort * inputPort(const int index=0) const
Returns the input port at index (default 0).
static int colorNameToIndex(const QString &color)
Maps a color name ("White","Red","Green","Blue","Purple") to indices 0–4.
virtual void save(QDataStream &stream, SerializationOptions options) const
const QVector< InputPort * > & inputs() const
Returns a const reference to the vector of all input ports.
void setName(const QString &name)
Sets the label text shown next to the port.
Definition Port.cpp:166
static QString readBoundedString(QDataStream &stream)
Reads a QString from stream, refusing to allocate more bytes than remain in the stream (prevents OOM ...
static QMap< QString, QVariant > readBoundedMetadata(QDataStream &stream)
Reads the file-level metadata QMap<QString,QVariant> from stream without calling QList::reserve() wit...
bool hasLockState(const QVersionNumber &v)
V3.1: Lock state for input elements; color for some display/button types.
Definition VersionInfo.h:51
bool hasQMapFormat(const QVersionNumber &v)
V4.1: Format changed from flat binary to keyed QMap; port serial IDs; rotation fix.
Definition VersionInfo.h:60
Compile-time-validatable subset of ElementMetadata.
Definition ElementInfo.h:21
static const bool registered
Definition Display16.cpp:61
static ElementMetadata metadata()
Definition Display16.cpp:31
static constexpr ElementConstraints constraints
Definition Display16.cpp:19
Self-registering element information trait.
Compile-time-registered properties for one element type.
Bundles all per-deserialization state so that load() overrides receive it through one explicit parame...
QVersionNumber version
File-format version read from the stream header.
Options passed to GraphicElement::save() (and friends); the save-side counterpart of SerializationCon...
SerializationPurpose purpose
What this serialization is for; see SerializationPurpose. Mandatory, no default.