Roomba App  1.0
joystick.cpp
Go to the documentation of this file.
1 
14 #include "joystick.hh"
15 
16 #include <QMouseEvent>
17 #include <QPainter>
18 #include <QStyleOption>
19 #include <math.h>
20 #include <QByteArray>
21 
22 Joystick::Joystick(QWidget* parent /* = nullptr */)
23  : QWidget(parent), _x(0), _y(0), _animation(new QParallelAnimationGroup(this)),
24  _xAnimation(new QPropertyAnimation(this, "x")), _yAnimation(new QPropertyAnimation(this, "y")),
25  _alignment(Qt::AlignTop | Qt::AlignLeft)
26 {
27  _xAnimation->setEndValue(0.f);
28  _xAnimation->setDuration(400);
29  _xAnimation->setEasingCurve(QEasingCurve::OutSine);
30 
31  _yAnimation->setEndValue(0.f);
32  _yAnimation->setDuration(400);
33  _yAnimation->setEasingCurve(QEasingCurve::OutSine);
34 
35  _animation->addAnimation(_xAnimation);
36  _animation->addAnimation(_yAnimation);
37 }
38 
40 
41 void Joystick::setX(const float& value)
42 {
43  _x = checkValue(value, -1.f, 1.f);
44 
45  qreal radius = (_bounds.width() - _knopBounds.width()) / 2;
46  _knopBounds.moveCenter(QPointF(_bounds.center().x() + _x * radius, _knopBounds.center().y()));
47 
48  update();
49  emit xChange(_x);
50 }
51 
52 void Joystick::setY(const float& value)
53 {
54  _y = checkValue(value, -1.f, 1.f);
55 
56  qreal radius = (_bounds.width() - _knopBounds.width()) / 2;
57  _knopBounds.moveCenter(QPointF(_knopBounds.center().x(), _bounds.center().y() - _y * radius));
58 
59  update();
60  emit yChange(_y);
61 }
62 
64 {
65  if(_xAnimation->parent() == _animation) return;
66  _animation->addAnimation(_xAnimation);
67 }
68 
70 {
71  if(_yAnimation->parent() == _animation) return;
72  _animation->addAnimation(_yAnimation);
73 }
74 
76 {
77  if(_xAnimation->parent() != _animation) return;
78  _animation->removeAnimation(_xAnimation);
79  _xAnimation->setParent(this);
80 }
81 
83 {
84  if(_yAnimation->parent() != _animation) return;
85  _animation->removeAnimation(_yAnimation);
86  _yAnimation->setParent(this);
87 }
88 
89 void Joystick::setAlignment(Qt::Alignment align)
90 {
91  _alignment = align;
92 }
93 
94 void Joystick::movePos(const QPoint& coordinates)
95 {
96  float xOffset = (coordinates.x() - _midPoint) / _midPoint;
97  float yOffset = (coordinates.y() - _midPoint) / _midPoint;
98  qreal radius = (_bounds.width() - _knopBounds.width()) / 2.0;
99 
100  QPointF position = QPointF(xOffset * radius + _bounds.center().x(), yOffset * radius + _bounds.center().y());
101  QPointF fromCenterToKnop = position - _bounds.center();
102 
103  fromCenterToKnop.setX(checkValue(fromCenterToKnop.x(), -radius, radius));
104  fromCenterToKnop.setY(checkValue(fromCenterToKnop.y(), -radius, radius));
105  _knopBounds.moveCenter(fromCenterToKnop + _bounds.center());
106 
107  update();
108 
109  if(radius == 0) return;
110  float x = (_knopBounds.center().x() - _bounds.center().x()) / radius;
111  float y = (-_knopBounds.center().y() + _bounds.center().y()) / radius;
112 
113  if(_x != x)
114  {
115  _x = x;
116  emit xChange(_x);
117  }
118 
119  if(_y != y)
120  {
121  _y = y;
122  emit yChange(_y);
123  }
124 }
125 
126 float Joystick::checkValue(const float& value, const float& min, const float& max) const
127 {
128  return (value < min) ? min : (value > max) ? max : value;
129 }
130 
131 void Joystick::resizeEvent(QResizeEvent* event)
132 {
133  Q_UNUSED(event)
134 
135  float a = qMin(width(), height());
136 
137  QPointF topleft;
138 
139  if(_alignment.testFlag(Qt::AlignTop))
140  {
141  topleft.setY(0);
142  }
143  else if(_alignment.testFlag(Qt::AlignVCenter))
144  {
145  topleft.setY(((height() - a) / 2));
146  }
147  else if(_alignment.testFlag(Qt::AlignBottom))
148  {
149  topleft.setY(height() - a);
150  }
151 
152  if(_alignment.testFlag(Qt::AlignLeft))
153  {
154  topleft.setX(0);
155  }
156  else if(_alignment.testFlag(Qt::AlignHCenter))
157  {
158  topleft.setX((width() - a) / 2);
159  }
160  else if(_alignment.testFlag(Qt::AlignRight))
161  {
162  topleft.setX(width() - a);
163  }
164 
165  _bounds = QRectF(topleft, QSize(a, a));
166  _knopBounds.setWidth(a * 0.3);
167  _knopBounds.setHeight(a * 0.3);
168 
169  qreal radius = (_bounds.width() - _knopBounds.width()) / 2;
170  _knopBounds.moveCenter(QPointF(_bounds.center().x() + _x * radius, _bounds.center().y() - _y * radius));
171 }
172 
173 void Joystick::paintEvent(QPaintEvent* event)
174 {
175  Q_UNUSED(event)
176 
177  QPainter painter(this);
178  painter.setRenderHint(QPainter::Antialiasing);
179 
180  // Background
181  QRadialGradient background(_bounds.center(), _bounds.width() / 2, _bounds.center());
182  background.setFocalRadius(_bounds.width() * 0.3);
183  background.setCenterRadius(_bounds.width() * 0.7);
184  background.setColorAt(0, Qt::white);
185  background.setColorAt(1, Qt::lightGray);
186 
187  painter.setPen(QPen(QBrush(Qt::gray), _bounds.width() * 0.005));
188  painter.setBrush(QBrush(background));
189  painter.drawEllipse(_bounds);
190 
191  // Crosshair
192  painter.setPen(QPen(QBrush(Qt::gray), _bounds.width() * 0.005));
193  painter.drawLine(QPointF(_bounds.left(), _bounds.center().y()),
194  QPointF(_bounds.center().x() - _bounds.width() * 0.35, _bounds.center().y()));
195  painter.drawLine(QPointF(_bounds.center().x() + _bounds.width() * 0.35, _bounds.center().y()),
196  QPointF(_bounds.right(), _bounds.center().y()));
197  painter.drawLine(QPointF(_bounds.center().x(), _bounds.top()),
198  QPointF(_bounds.center().x(), _bounds.center().y() - _bounds.width() * 0.35));
199  painter.drawLine(QPointF(_bounds.center().x(), _bounds.center().y() + _bounds.width() * 0.35),
200  QPointF(_bounds.center().x(), _bounds.bottom()));
201 
202  // Knob
203  if(!this->isEnabled()) return;
204 
205  // Knop base
206  painter.setPen(QPen(Qt::lightGray, _knopBounds.width() / 2.5, Qt::SolidLine, Qt::RoundCap));
207  painter.drawLine(_bounds.center(), _knopBounds.center());
208 
209  QRadialGradient knob(_knopBounds.center(), _knopBounds.width() / 2, _knopBounds.center());
210  knob.setColorAt(0, Qt::gray);
211  knob.setColorAt(1, Qt::darkGray);
212  knob.setFocalRadius(_knopBounds.width() * 0.2);
213  knob.setCenterRadius(_knopBounds.width() * 0.5);
214 
215  painter.setPen(QPen(QBrush(Qt::darkGray), _bounds.width() * 0.005));
216  painter.setBrush(QBrush(knob));
217  painter.drawEllipse(_knopBounds);
218 }
const float _midPoint
Middle value of raw analog joystick coordinates.
Definition: joystick.hh:144
float checkValue(const float &value, const float &min, const float &max) const
Check if coordinate value is in proper range.
Definition: joystick.cpp:126
void addYAnimation()
Add animation for y axis to return knop to home position.
Definition: joystick.cpp:69
void yChange(float value)
Signal emitted in order to realize value change of y coordinate.
Qt::Alignment _alignment
Alignment used in resizeEvent.
Definition: joystick.hh:184
~Joystick()
Delete Joystick object.
Definition: joystick.cpp:39
QPropertyAnimation * _xAnimation
Animation on x axis when knop is returning home position.
Definition: joystick.hh:174
void removeYAnimation()
Remove animation for y axis to return knop to home position.
Definition: joystick.cpp:82
QPropertyAnimation * _yAnimation
Animation on y axis when knop is returning home position.
Definition: joystick.hh:179
void movePos(const QPoint &coordinates)
Change knop coordinates.
Definition: joystick.cpp:94
QRectF _knopBounds
Bounds of knop.
Definition: joystick.hh:164
void setX(const float &value)
Set value of x coordinate.
Definition: joystick.cpp:41
void setY(const float &value)
Set value of y coordinate.
Definition: joystick.cpp:52
float _y
Value of y coordinate.
Definition: joystick.hh:154
float _x
Value of x coordinate.
Definition: joystick.hh:149
void removeXAnimation()
Remove animation for x axis to return knop to home position.
Definition: joystick.cpp:75
virtual void paintEvent(QPaintEvent *event) override
Draw analog joystick with it's background.
Definition: joystick.cpp:173
float y
Definition: joystick.hh:28
QParallelAnimationGroup * _animation
Animation group used to animate knop returning to home position.
Definition: joystick.hh:169
void addXAnimation()
Add animation for x axis to return knop to home position.
Definition: joystick.cpp:63
void setAlignment(Qt::Alignment align)
Set alignment needed for resizeEvent to work.
Definition: joystick.cpp:89
void resizeEvent(QResizeEvent *event) override
Event handler to change size of widget.
Definition: joystick.cpp:131
Joystick(QWidget *parent=nullptr)
Construct new Joystick object.
Definition: joystick.cpp:22
float x
Definition: joystick.hh:27
void xChange(float value)
Signal emitted in order to realize value change of x coordinate.
QRectF _bounds
Bounds of background.
Definition: joystick.hh:159
Header file for Joystick class.