1.10
gauge.h
1/*
2 * Copyright (C) 2018 Microchip Technology Inc. All rights reserved.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6#ifndef EGT_GAUGE_H
7#define EGT_GAUGE_H
8
14#include <egt/color.h>
15#include <egt/detail/math.h>
16#include <egt/detail/meta.h>
17#include <egt/frame.h>
18#include <egt/image.h>
19#include <egt/widget.h>
20#include <memory>
21#include <vector>
22
23namespace egt
24{
25inline namespace v1
26{
27namespace experimental
28{
29class Gauge;
30
34class EGT_API GaugeLayer : public Widget
35{
36public:
37
43 explicit GaugeLayer(const Image& image = {}) noexcept;
44
51 explicit GaugeLayer(Gauge& gauge, const Image& image = {}) noexcept;
52
53 void draw(Painter& painter, const Rect& rect) override;
54
62 void image(const Image& image)
63 {
64 m_image = image;
65 resize(m_image.size());
66 damage();
67 }
68
69 void mask_color(const Color& color)
70 {
71 if (detail::change_if_diff<>(m_mask_color, color))
72 damage();
73 }
74
78 EGT_NODISCARD Gauge* gauge() const { return m_gauge; }
79
80protected:
81
87 virtual void gauge(Gauge* gauge)
88 {
89 if (!m_gauge || !gauge)
90 {
91 if (detail::change_if_diff<>(m_gauge, gauge))
92 damage();
93 }
94 }
95
98
100 Gauge* m_gauge{nullptr};
101
104
105 friend class Gauge;
106};
107
115class EGT_API NeedleLayer : public GaugeLayer
116{
117public:
118
127 using GaugeLayer::GaugeLayer;
128
137 explicit NeedleLayer(const Image& image,
138 float min,
139 float max,
140 float angle_start = 0,
141 float angle_stop = 360,
142 bool clockwise = true) noexcept;
143
144 void draw(Painter& painter, const Rect& rect) override;
145
149 EGT_NODISCARD float angle_start() const { return m_angle_start; }
150
156 float angle_start(float angle_start)
157 {
158 float orig = m_angle_start;
159 if (detail::change_if_diff<float>(m_angle_start, angle_start))
160 damage();
161 return orig;
162 }
163
167 EGT_NODISCARD float angle_stop() const { return m_angle_stop; }
168
174 float angle_stop(float angle_stop)
175 {
176 float orig = m_angle_stop;
177 if (detail::change_if_diff<float>(m_angle_stop, angle_stop))
178 damage();
179 return orig;
180 }
181
183 EGT_NODISCARD float min() const { return m_min; }
184
190 float min(float min)
191 {
192 float orig = m_min;
193 if (detail::change_if_diff<float>(m_min, min))
194 {
195 value(m_value);
196 damage();
197 }
198
199 return orig;
200 }
201
203 EGT_NODISCARD float max() const { return m_max; }
204
210 float max(float max)
211 {
212 float orig = m_max;
213 if (detail::change_if_diff<float>(m_max, max))
214 {
215 value(m_value);
216 damage();
217 }
218
219 return orig;
220 }
221
223 EGT_NODISCARD float value() const { return m_value; }
224
232 float value(float value)
233 {
234 auto orig = m_value;
235
236 value = std::round(detail::clamp<float>(value, m_min, m_max));
237
238 if (!detail::float_equal(m_value, value))
239 {
240 damage(rectangle_of_rotated());
241 m_value = value;
242 on_value_changed.invoke();
243 damage(rectangle_of_rotated());
244 }
245
246 return orig;
247 }
248
252 EGT_NODISCARD PointF needle_point() const { return m_point; }
253
263 void needle_point(const PointF& point)
264 {
265 if (detail::change_if_diff<PointF>(m_point, point))
266 {
267 auto dim = std::max(m_image.width(), m_image.height());
268 auto circle = Circle(Point(m_point.x(), m_point.y()), dim);
269 auto superrect = circle.rect();
270
271 // real widget size is the big rect, center is a common point
272 resize(superrect.size());
273 move_to_center(superrect.center());
274 }
275 }
276
280 EGT_NODISCARD PointF needle_center() const { return m_center; }
281
289 void needle_center(const PointF& center)
290 {
291 if (detail::change_if_diff<PointF>(m_center, center))
292 damage();
293 }
294
298 EGT_NODISCARD bool clockwise() const { return m_clockwise; }
299
305 void clockwise(bool value)
306 {
307 if (detail::change_if_diff<>(m_clockwise, value))
308 damage();
309 }
310
311protected:
312
314
316 void gauge(Gauge* gauge) override;
317
319 float m_min{0.0};
320
322 float m_max{0.0};
323
325 float m_value{0.0};
326
328 float m_angle_start{0.0};
329
331 float m_angle_stop{360.0};
332
334 bool m_clockwise{true};
335
338
341};
342
381// NOLINTNEXTLINE(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
382class EGT_API Gauge : public Frame
383{
384public:
385
390 explicit Gauge(const Rect& rect = {},
391 const Flags& flags = {}) noexcept;
392
398 Gauge(Frame& parent, const Rect& rect,
399 const Flags& flags = {}) noexcept;
400
401 using Frame::add;
402
411 void add(const std::shared_ptr<GaugeLayer>& layer);
412
416 void add(GaugeLayer& layer)
417 {
418 // Nasty, but it gets the job done. If a widget is passed in as a
419 // reference, we don't own it, so create a "pointless" shared_ptr that
420 // will not delete it.
421 auto w = std::shared_ptr<GaugeLayer>(&layer, [](GaugeLayer*) {});
422 add(w);
423 }
424
425 using Frame::remove;
426
428 void remove(GaugeLayer* layer);
429
430 ~Gauge() noexcept override;
431
432protected:
433
437 EGT_NODISCARD Size super_size() const
438 {
439 Rect result = content_area().size();
440 for (const auto& layer : m_layers)
441 result = Rect::merge(result, layer->box() + Size(moat() * 2, moat() * 2));
442 return result.size();
443 }
444
446 using LayerArray = std::vector<std::shared_ptr<GaugeLayer>>;
447
450};
451
452}
453}
454}
455
456#endif
A basic circle with a center point and radius.
Definition geometry.h:1204
32 bit RGBA color.
Definition color.h:41
Utility class for managing a set of flags with the ability to observe changes to the flags.
Definition flags.h:40
A Frame is a Widget that has children widgets.
Definition frame.h:45
Raster image resource used for drawing or displaying.
Definition image.h:39
Drawing interface for 2D graphics.
Definition painter.h:45
EGT_NODISCARD constexpr const SizeType< Dim, DimCompat > & size() const noexcept
Get the SizeType of the rectangle.
Definition geometry.h:738
Signal class used for defining a signal and dispatching events.
Definition signal.h:30
void invoke(Args... args)
Invoke all handlers with the specified args.
Definition signal.h:85
Base Widget class.
Definition widget.h:53
A layer of a Gauge.
Definition gauge.h:35
void mask_color(const Color &color)
Definition gauge.h:69
GaugeLayer(Gauge &gauge, const Image &image={}) noexcept
Construct a gauge layer with an image and a parent gauge.
GaugeLayer(const Image &image={}) noexcept
Construct a gauge layer with an image.
void draw(Painter &painter, const Rect &rect) override
Draw the widget.
void image(const Image &image)
Set the image of the gauge layer.
Definition gauge.h:62
virtual void gauge(Gauge *gauge)
Normally this does not need to be called directly.
Definition gauge.h:87
Color m_mask_color
Optional mask color.
Definition gauge.h:103
EGT_NODISCARD Gauge * gauge() const
Get the gauge of the layer.
Definition gauge.h:78
Image m_image
The Layer image.
Definition gauge.h:97
A Gauge Widget that is composed of GaugeLayer layers.
Definition gauge.h:383
std::vector< std::shared_ptr< GaugeLayer > > LayerArray
Type for an array of layers.
Definition gauge.h:446
void add(const std::shared_ptr< GaugeLayer > &layer)
Add a GaugeLayer to the Gauge.
~Gauge() noexcept override
Gauge(const Rect &rect={}, const Flags &flags={}) noexcept
LayerArray m_layers
The layer's of the gauge.
Definition gauge.h:449
void add(GaugeLayer &layer)
Add a GaugeLayer to the Gauge.
Definition gauge.h:416
Gauge(Frame &parent, const Rect &rect, const Flags &flags={}) noexcept
void remove(GaugeLayer *layer)
Remove a layer from the gauge.
Special GaugeLayer that deals with a rotating needle.
Definition gauge.h:116
float min(float min)
Set the min value.
Definition gauge.h:190
EGT_NODISCARD bool clockwise() const
Get the clockwise value.
Definition gauge.h:298
EGT_NODISCARD float max() const
Get the max value.
Definition gauge.h:203
PointF m_center
Center point of the needle.
Definition gauge.h:337
EGT_NODISCARD PointF needle_center() const
Get the needle center.
Definition gauge.h:280
void needle_center(const PointF &center)
Set the needle center.
Definition gauge.h:289
float angle_start(float angle_start)
Set the start angle of the needle.
Definition gauge.h:156
EGT_NODISCARD PointF needle_point() const
Get the needle point.
Definition gauge.h:252
void clockwise(bool value)
Set the clockwise value.
Definition gauge.h:305
NeedleLayer(const Image &image, float min, float max, float angle_start=0, float angle_stop=360, bool clockwise=true) noexcept
EGT_NODISCARD float min() const
Get the min value.
Definition gauge.h:183
float value(float value)
Set the value.
Definition gauge.h:232
Signal on_value_changed
Event signal.
Definition gauge.h:124
EGT_NODISCARD float value() const
Get the value of the needle.
Definition gauge.h:223
EGT_NODISCARD float angle_stop() const
Get the angle stop value.
Definition gauge.h:167
float angle_stop(float angle_stop)
Set the stop angle of the needle.
Definition gauge.h:174
void needle_point(const PointF &point)
Set the needle point.
Definition gauge.h:263
float max(float max)
Set the max value.
Definition gauge.h:210
PointF m_point
Rotate point of the needle on the gauge.
Definition gauge.h:340
T & center(T &widget)
Helper to set alignment of a widget.
Definition widgetflags.h:416
EGT framework namespace.
Definition animation.h:24