FlowArithmeticCalculator 1.0.0
Flow Arithmetic Calculator
Loading...
Searching...
No Matches
SkiaBaseBlockRenderer.cpp
Go to the documentation of this file.
2
3namespace gui::elements {
4 // NOLINTBEGIN(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions)
6 SkCanvas* canvas,
7 int mouseX,
8 int mouseY,
9 bool isHovered) { // dark gray outline
10 static SkPaint const blockOutlinePaint = []() {
11 SkPaint paint;
12
14 paint.setStyle(SkPaint::Style::kStroke_Style);
16 paint.setAntiAlias(true);
17
18 return paint;
19 }();
20
21 // red hovered outline
22 static SkPaint const blockOutlineHoveredPaint = []() {
23 SkPaint paint;
24
26 paint.setStyle(SkPaint::Style::kStroke_Style);
28 paint.setAntiAlias(true);
29
30 return paint;
31 }();
32
33 // blueish hovered outline
34 static SkPaint const portOutlineHoveredPaint = []() {
35 SkPaint paint;
36
38 paint.setStyle(SkPaint::Style::kStroke_Style);
40 paint.setAntiAlias(true);
41
42 return paint;
43 }();
44
45 static SkPaint const portOutlinePaint = []() {
46 SkPaint paint;
47
49 paint.setStyle(SkPaint::Style::kStroke_Style);
51 paint.setAntiAlias(true);
52
53 return paint;
54 }();
55
56 // light blue gray fill
57 static SkPaint const blockFillPaint = []() {
58 SkPaint paint;
59
61 paint.setStyle(SkPaint::Style::kFill_Style);
62
63 return paint;
64 }();
65
66 static SkPaint const textPaint = []() {
67 SkPaint paint;
68
70 paint.setStyle(SkPaint::Style::kFill_Style);
71 paint.setAntiAlias(true);
72
73 return paint;
74 }();
75
76 const auto& inputPorts = block->getInputPorts();
77 const auto& outputPorts = block->getOutputPorts();
78
79 const auto leftX = block->getLeftX();
80 const auto rightX = block->getRightX();
81 const auto topY = block->getTopY();
82 const auto bottomY = block->getBottomY();
83 const auto cy = block->getCy();
84 const auto width = block->getWidth();
85 auto& portCoordinates = block->getPortCoordinates();
86
87 // note 1: the below uses int arithmetic for performance optimization; the assumption is
88 // that the constants are for sure integers, which is guarded by static_assert in the header
89 // ---
90 // note 2: below a sum of port circle radius / 2 + port circle outline width is used
91 // instead of TOTAL_PORT_RADIUS, since leftX is already at the edge of the block; therefore
92 // the offset must be by half of the radius + the outline width
93 const auto portCircleOffsetFromBlockEdge =
96 const auto inputCx = leftX + portCircleOffsetFromBlockEdge;
97 const auto outputCx = rightX - portCircleOffsetFromBlockEdge;
98
99 const auto inputsTotalHeight =
100 // NOLINTNEXTLINE(bugprone-implicit-widening-of-multiplication-result)
101 (business_logic::constants::TOTAL_PORT_RADIUS * 2 * inputPorts.size()) +
102 (business_logic::constants::PORT_CIRCLE_MARGIN * (inputPorts.size() - 1));
103
104 const auto outputsTotalHeight =
105 // NOLINTNEXTLINE(bugprone-implicit-widening-of-multiplication-result)
106 (business_logic::constants::TOTAL_PORT_RADIUS * 2 * outputPorts.size()) +
107 (business_logic::constants::PORT_CIRCLE_MARGIN * (outputPorts.size() - 1));
108
109 auto inputCy = static_cast<int>(std::round(cy - (inputsTotalHeight / 2.0F)));
110 auto outputCy = static_cast<int>(std::round(cy - (outputsTotalHeight / 2.0F)));
111
112 // draw the block
113 // NOLINTNEXTLINE(bugprone-narrowing-conversions, cppcoreguidelines-narrowing-conversions)
114 canvas->drawRect(SkRect::MakeLTRB(leftX, topY, rightX, bottomY),
115 isHovered ? blockOutlineHoveredPaint : blockOutlinePaint);
116 // NOLINTNEXTLINE(bugprone-narrowing-conversions, cppcoreguidelines-narrowing-conversions)
117 canvas->drawRect(SkRect::MakeLTRB(leftX, topY, rightX, bottomY), blockFillPaint);
118
119 const auto captionFont =
120 gui::renderer::FontManager::getFontForVariant(components::UIText::Variant::Caption);
121 const auto captionFontSize = captionFont.getSize();
122
123 const auto* blockNameCstr = magic_enum::enum_name(block->getBlockType()).data();
124 auto blockNameWidth =
125 captionFont.measureText(blockNameCstr, strlen(blockNameCstr), SkTextEncoding::kUTF8);
126
127 // draw the block name
128 canvas->drawString(blockNameCstr,
129 leftX + (static_cast<SkScalar>(width) / 2.0F) - (blockNameWidth / 2),
130 cy + (captionFontSize / 4),
131 captionFont,
132 textPaint);
133
134 // draw the input ports
135 for (size_t i = 0; i < inputPorts.size(); i++) {
136 // advance to the center of the circle
138
139 // update the port coordinates map after advancing
140 portCoordinates[&inputPorts[i]] = {.x = inputCx, .y = inputCy};
141
142 // check if port hovered after advancing to the center
143 bool const isPortHovered =
145 mouseX,
146 mouseY,
147 inputCx,
148 inputCy,
150
151 const SkPaint& renderOutlinePaint =
152 isPortHovered ? portOutlineHoveredPaint : portOutlinePaint;
153
154 canvas->drawCircle(inputCx,
155 inputCy,
157 renderOutlinePaint);
158 canvas->drawCircle(
159 inputCx, inputCy, business_logic::constants::PORT_CIRCLE_RADIUS, blockFillPaint);
160
161 if (isPortHovered) {
162 const auto* cstr = inputPorts[i].name.c_str();
163
164 // measure the text
165 SkScalar const captionWidth =
166 captionFont.measureText(cstr, strlen(cstr), SkTextEncoding::kUTF8);
167
168 // render port name to the left of the port
169 canvas->drawString(cstr,
171 captionFontSize - captionWidth,
173 (captionFontSize / 4),
174 captionFont,
175 textPaint);
176 }
177
180 }
181
182 // draw the output ports
183 for (size_t i = 0; i < outputPorts.size(); i++) {
184 // advance to the center of the circle
186
187 // update the port coordinates map after advancing
188 portCoordinates[&outputPorts[i]] = {.x = outputCx, .y = outputCy};
189
190 // check if port hovered after advancing to the center
191 bool const isPortHovered =
193 mouseX,
194 mouseY,
195 outputCx,
196 outputCy,
198
199 const SkPaint& renderOutlinePaint =
200 isPortHovered ? portOutlineHoveredPaint : portOutlinePaint;
201
202 canvas->drawCircle(outputCx,
203 outputCy,
205 renderOutlinePaint);
206 canvas->drawCircle(
207 outputCx, outputCy, business_logic::constants::PORT_CIRCLE_RADIUS, blockFillPaint);
208
209 if (isPortHovered) {
210 const auto* cstr = outputPorts[i].name.c_str();
211
212 // render port name to the right of the port
213 canvas->drawString(
214 cstr,
215 outputCx + business_logic::constants::TOTAL_PORT_RADIUS_HALF + captionFontSize,
217 (captionFontSize / 4),
218 captionFont,
219 textPaint);
220 }
221
224 }
225
226 if (auto blockValue = block->getValueToRenderAboveBlock(isHovered)) {
227 renderValueAboveBlock(block, canvas, isHovered, blockValue.value());
228 }
229 }
230
233 SkCanvas* canvas,
234 [[maybe_unused]] bool isHovered,
235 const std::string& blockValue) {
236 const auto leftX = block->getLeftX();
237 const auto topY = block->getTopY();
238 const auto width = block->getWidth();
239
240 const auto* blockValueCstr = blockValue.c_str();
241 auto blockValueWidth = gui::renderer::FontManager::captionFont.measureText(
242 blockValueCstr, strlen(blockValueCstr), SkTextEncoding::kUTF8);
243
244 canvas->drawString(blockValueCstr,
245 leftX + (static_cast<SkScalar>(width) / 2.0F) - (blockValueWidth / 2.0F),
249 }
250 // NOLINTEND(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions)
251} // namespace gui::elements
The base class for all blocks, containing common functionality and members.
Definition BaseBlock.h:36
int getBottomY() const
Gets the bottom y coordinate of the block.
Definition BaseBlock.h:212
int getRightX() const
Gets the right x coordinate of the block.
Definition BaseBlock.h:200
int getCy() const
Gets the center y coordinate of the block.
Definition BaseBlock.h:188
virtual const std::vector< structures::Port > & getOutputPorts() const =0
Gets the output ports of the block.
int getLeftX() const
Gets the left x coordinate of the block.
Definition BaseBlock.h:194
virtual const std::vector< structures::Port > & getInputPorts() const =0
Gets the input ports of the block.
const business_logic::geometry::Point2D & getPortCoordinates(const structures::Port *port) const
Gets the coordinates of a port.
int getWidth() const
Gets the width of the block.
Definition BaseBlock.h:218
virtual BlockType getBlockType() const =0
Gets the type of the block.
int getTopY() const
Gets the top y coordinate of the block.
Definition BaseBlock.h:206
virtual std::optional< std::string > getValueToRenderAboveBlock(bool isHovered)
Wrapper that gets the value of the output port above the block; if more or less than 1 output port is...
Definition BaseBlock.cpp:81
static void render(business_logic::elements::blocks::BaseBlock *block, SkCanvas *canvas, int mouseX, int mouseY, bool isHovered)
Renders a block on an SkCanvas.
static void renderValueAboveBlock(const business_logic::elements::blocks::BaseBlock *block, SkCanvas *canvas, bool isHovered, const std::string &blockValue)
Renders the value above the block.
static SkPaint textFontFillPaint
The paint for the text font fill.
Definition FontManager.h:43
static const SkFont & getFontForVariant(const business_logic::components::UIText::Variant &variant)
Gets the font for the given variant.
static SkFont captionFont
The font for the caption font.
Definition FontManager.h:68
constexpr int TOTAL_PORT_HITBOX_RADIUS
Definition constants.h:26
constexpr int PORT_CIRCLE_OUTLINE_WIDTH
Definition constants.h:20
constexpr int PORT_CIRCLE_RADIUS_HALF
Definition constants.h:18
constexpr int PORT_CIRCLE_MARGIN
Definition constants.h:30
constexpr int TOTAL_PORT_RADIUS_HALF
Definition constants.h:28
constexpr int TOTAL_PORT_RADIUS
Definition constants.h:27
constexpr int BLOCK_OUTLINE_WIDTH
Definition constants.h:34
constexpr int PORT_CIRCLE_RADIUS
Definition constants.h:14
bool isCircleHovered(int mouseX, int mouseY, int cX, int cY, int radius)
Check if a point is within a circle.
Definition helpers.cpp:4
The GUI counterpart carrying implementations integrating with business_logic::elements.
const SkColor TEXT_COLOR
Definition colors.cpp:27
const SkColor BLOCK_BACKGROUND_COLOR
Definition colors.cpp:21
const SkColor BLOCK_PORT_OUTLINE_COLOR
Definition colors.cpp:24
const SkColor BLOCK_OUTLINE_COLOR
Definition colors.cpp:15
const SkColor PURPLE_BLUE
Definition colors.cpp:6
const SkColor BLOCK_HOVERED_OUTLINE_COLOR
Definition colors.cpp:18