summaryrefslogtreecommitdiff
path: root/ui/clickablelabel.h
blob: 5e8c2cbf12235ec54aad03b0a9018c600027844a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#pragma once

#include <QtCore/QTimer>
#include <QtGui/QColor>
#include <QtGui/QPainter>
#include <QtGui/QPaintEvent>
#include <QtWidgets/QLabel>
#include "uicontext.h"

/*!

	\defgroup clickablelabel ClickableLabel
 	\ingroup uiapi
*/

/*!

    \ingroup clickablelabel
*/
struct BINARYNINJAUIAPI IconImage
{
	QImage activeOriginal, inactiveOriginal;
	QImage active, activeHover;
	QImage inactive, inactiveHover;

	static IconImage generate(const QImage& activeSrc, const QImage& inactiveSrc);
};


/*!

    \ingroup clickablelabel
*/
class BINARYNINJAUIAPI ClickableLabel : public QLabel
{
	Q_OBJECT

	bool m_passThroughMousePressEvent = false;

  public:
	ClickableLabel(QWidget* parent = nullptr, const QString& name = "") : QLabel(parent) { setText(name); }

	// FIXME: The new UI header in the pane system has some keyboard focus issues; so consuming mousePressEvent seems to resolve them
	// Since I can't repro the exact issues this allows the mouse event to pass through when needed.
	void passThroughMousePressEvent(bool enable) { m_passThroughMousePressEvent = enable; }

  Q_SIGNALS:
	void clicked();

  protected:
	void mousePressEvent(QMouseEvent* event) override { if (m_passThroughMousePressEvent) { QLabel::mousePressEvent(event); } }
	void mouseReleaseEvent(QMouseEvent* event) override
	{
		if (event->button() == Qt::LeftButton)
			Q_EMIT clicked();
	}
};


/*!

    \ingroup clickablelabel
*/
class BINARYNINJAUIAPI ClickableIcon : public QWidget
{
	Q_OBJECT

	IconImage m_image;
	bool m_canToggle = false;
	bool m_active = true;
	bool m_hover = false;
	double m_opacity = 1.0;
	QTimer* m_timer;

  public:
	ClickableIcon(const QImage& activeIcon, const QImage& inactiveIcon, const QSize& desiredPointSize);
	ClickableIcon(const QImage& icon, const QSize& desiredPointSize) : ClickableIcon(icon, icon, desiredPointSize) {}

	void setAllowToggle(bool canToggle);
	void setActive(bool state);
	bool active() const { return m_active; }

	void setImage(const QImage& icon);
	void setImage(const QImage& activeIcon, const QImage& inactiveIcon);

	Q_PROPERTY(QSize desiredPointSize READ desiredPointSize WRITE setDesiredPointSize)
	QSize desiredPointSize() const { return rect().size(); }
	void setDesiredPointSize(const QSize& size) { setFixedSize(size); }
	Q_PROPERTY(double opacity READ opacity WRITE setOpacity)
	double opacity() const { return m_opacity; }
	void setOpacity(double opacity)
	{
		m_opacity = opacity;
		update();
	};

  Q_SIGNALS:
	void clicked();
	void toggle(bool newState);

  private Q_SLOTS:
	void underMouseTimerEvent();
	void handleToggle();

  protected:
	void enterEvent(QEnterEvent* event) override;
	void leaveEvent(QEvent* event) override;
	void paintEvent(QPaintEvent* event) override;
	void mousePressEvent(QMouseEvent*) override {}
	void mouseReleaseEvent(QMouseEvent* event) override;
};


/*!

    \ingroup clickablelabel
*/
class BINARYNINJAUIAPI ClickableStateLabel : public ClickableLabel
{
	Q_OBJECT

	QString m_name;
	QString m_altName;
	bool m_state = true;
	bool m_stateEffectEnabled = false;
	bool m_altStateEffect = false;
	QPalette::ColorRole m_altOverlayColorRole;
	int m_alpha;

  public:
	ClickableStateLabel(QWidget* parent, const QString& name, const QString& altName) :
	    ClickableLabel(parent, name), m_name(name), m_altName(altName)
	{}

	bool getState() { return m_state; }

	void setDisplayState(bool state)
	{
		m_state = state;
		setText(m_state ? m_name : m_altName);
	}

	void setAlternateTransparency(QPalette::ColorRole colorRole, int alpha, bool state)
	{
		m_altOverlayColorRole = colorRole;
		m_alpha = alpha;
		m_altStateEffect = state;
		m_stateEffectEnabled = true;
	}

  protected:
	void paintEvent(QPaintEvent* event) override
	{
		ClickableLabel::paintEvent(event);
		if (m_stateEffectEnabled && (m_state == m_altStateEffect))
		{
			QPainter p(this);
			QColor overlayColor = palette().color(m_altOverlayColorRole);
			overlayColor.setAlpha(m_alpha);
			p.fillRect(event->rect(), overlayColor);
		}
	}
};