!XT (BREAK-16) (Sandbox) Remove double-newlines at the end of files.
[CRYENGINE.git] / Code / Sandbox / Plugins / EditorCommon / QTrackingTooltip.cpp
blobdcaf3e54734432f222ae135dc401eb630f715df7
1 // Copyright 2001-2018 Crytek GmbH / Crytek Group. All rights reserved.
3 #include "StdAfx.h"
4 #include "QTrackingTooltip.h"
5 #include <QToolTip>
6 #include <QApplication>
7 #include <QDesktopWidget>
9 QSharedPointer<QTrackingTooltip> QTrackingTooltip::m_instance;
11 QTrackingTooltip::QTrackingTooltip(QWidget* parent)
12 : QFrame(parent)
13 , m_isTracking(false)
14 , m_cursorOffset(0, 0)
15 , m_autoHide(true)
17 setWindowFlags(Qt::ToolTip | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
18 setFocusPolicy(Qt::FocusPolicy::NoFocus);
19 setAttribute(Qt::WA_ShowWithoutActivating);
20 setAttribute(Qt::WA_TransparentForMouseEvents);
23 QTrackingTooltip::~QTrackingTooltip(void)
27 void QTrackingTooltip::Show()
29 raise();
30 show();
33 void QTrackingTooltip::ShowTextTooltip(const QString& str, const QPoint& p)
35 if (m_instance)
37 if (!str.isEmpty() && m_instance->SetText(str))
39 m_instance->SetPos(p);
40 return;
42 else
43 QTrackingTooltip::HideTooltip();
46 if (!str.isEmpty())
48 m_instance = QSharedPointer<QTrackingTooltip>(new QTrackingTooltip(), &QObject::deleteLater);
49 m_instance->SetText(str);
50 m_instance->Show();
51 m_instance->SetPos(p);
55 void QTrackingTooltip::ShowTrackingTooltip(QSharedPointer<QTrackingTooltip>& tooltip, const QPoint& cursorOffset)
57 if (m_instance && m_instance != tooltip)
59 QTrackingTooltip::HideTooltip();
62 if (tooltip)
64 m_instance = tooltip;
65 m_instance->Show();
67 if (!cursorOffset.isNull())
68 m_instance->SetPosCursorOffset(cursorOffset);
69 else if (m_instance->GetCursorOffset().isNull())
70 m_instance->SetPosCursorOffset(QPoint(25, 25));
71 else
72 m_instance->SetPosCursorOffset();
74 m_instance->m_isTracking = true;
75 qApp->installEventFilter(m_instance.data());
79 void QTrackingTooltip::HideTooltip()
81 if (m_instance)
83 qApp->removeEventFilter(m_instance.data());
84 m_instance->m_isTracking = false;
85 m_instance->setVisible(false);
86 m_instance.clear();
90 void QTrackingTooltip::HideTooltip(QTrackingTooltip* tooltip)
92 if (m_instance == tooltip)
93 HideTooltip();
96 bool QTrackingTooltip::SetText(const QString& str)
98 QLabel* label = findChild<QLabel*>("QTrackingTooltipLabel");
99 if (label)
101 label->setText(str);
102 adjustSize();
103 return true;
106 if (layout())
107 return false;
109 label = new QLabel(this, Qt::WindowStaysOnTopHint);
110 label->setFrameStyle(QFrame::Panel);
111 label->setFont(QToolTip::font());
112 label->setPalette(QToolTip::palette());
113 label->setText(str);
114 label->setObjectName("QTrackingTooltipLabel");
115 label->adjustSize();
117 auto layout = new QVBoxLayout();
118 layout->setMargin(1);
119 layout->addWidget(label);
120 setLayout(layout);
121 return true;
124 bool QTrackingTooltip::SetPixmap(const QPixmap& pixmap)
126 QLabel* label = findChild<QLabel*>("QTrackingTooltipLabel");
127 if (label)
129 label->setPixmap(pixmap);
130 adjustSize();
131 return true;
134 if (layout())
135 return false;
137 label = new QLabel();
138 label->setFrameStyle(QFrame::Panel);
139 label->setPixmap(pixmap);
140 label->setObjectName("QTrackingTooltipLabel");
141 label->adjustSize();
143 auto layout = new QVBoxLayout();
144 layout->setMargin(1);
145 layout->addWidget(label);
146 setLayout(layout);
147 return true;
150 void QTrackingTooltip::SetPos(const QPoint& p)
152 move(AdjustPosition(p));
155 void QTrackingTooltip::SetPosCursorOffset(const QPoint& p)
157 if(!p.isNull())
158 m_cursorOffset = p;
160 SetPos(QCursor::pos() + m_cursorOffset);
163 QPoint QTrackingTooltip::AdjustPosition(QPoint p) const
165 //The tooltip position may never overlap the cursor (otherwise we have a leave event and the tooltip disappears)
167 QRect rect = this->rect();
168 QRect screen = QApplication::desktop()->screenGeometry(GetToolTipScreen());
170 //see qtooltip.cpp
171 if (p.x() + rect.width() > screen.x() + screen.width())
172 p.rx() -= 4 + rect.width();
173 if (p.y() + rect.height() > screen.y() + screen.height())
174 p.ry() -= 24 + rect.height();
175 if (p.y() < screen.y())
176 p.setY(screen.y());
177 if (p.x() + rect.width() > screen.x() + screen.width())
178 p.setX(screen.x() + screen.width() - rect.width());
179 if (p.x() < screen.x())
180 p.setX(screen.x());
181 if (p.y() + rect.height() > screen.y() + screen.height())
182 p.setY(screen.y() + screen.height() - rect.height());
184 QRect futureRect(p.x(), p.y(), rect.width(), rect.height());
185 const auto cursor = QCursor::pos();
186 if (futureRect.contains(cursor))
188 //find closest edge
189 QPoint offset;
191 int diff = cursor.x() - futureRect.left();
192 int minDiff = diff;
193 offset = QPoint(diff + abs(m_cursorOffset.x()) + 1, 0);
195 diff = futureRect.right() - cursor.x();
196 if (diff < minDiff)
198 minDiff = diff;
199 offset = QPoint(-diff - abs(m_cursorOffset.x()) - 1, 0);
202 diff = cursor.y() - futureRect.top();
203 if (diff < minDiff)
205 minDiff = diff;
206 offset = QPoint(0, diff + abs(m_cursorOffset.y()) + 1);
209 diff = futureRect.bottom() - cursor.y();
210 if (diff < minDiff)
212 minDiff = diff;
213 offset = QPoint(0, -diff - abs(m_cursorOffset.y()) - 1);
216 p += offset;
218 CRY_ASSERT(!QRect(p.x(), p.y(), rect.width(), rect.height()).contains(cursor));
221 return p;
224 int QTrackingTooltip::GetToolTipScreen() const
226 if (QApplication::desktop()->isVirtualDesktop())
227 return QApplication::desktop()->screenNumber(QCursor::pos());
228 else
229 return QApplication::desktop()->screenNumber(this);
232 //Inspired from qtooltip.cpp
233 //Note that this code originally had special cases for macOS and QNX.
234 bool QTrackingTooltip::eventFilter(QObject* object, QEvent* event)
236 switch (event->type())
238 case QEvent::Leave:
239 //Note: here we may actually want to start a hide timer instead,
240 //as we could still be wanting to display the same tooltip.
241 //Not useful yet but will be.
242 case QEvent::WindowActivate:
243 case QEvent::WindowDeactivate:
244 case QEvent::FocusIn:
245 case QEvent::FocusOut:
246 case QEvent::MouseButtonPress:
247 case QEvent::MouseButtonRelease:
248 case QEvent::MouseButtonDblClick:
249 case QEvent::Wheel:
250 if (m_autoHide)
252 QTrackingTooltip::HideTooltip();
254 break;
255 case QEvent::MouseMove:
256 if (m_isTracking)
258 SetPosCursorOffset(m_cursorOffset);
260 default:
261 break;
263 return false;
266 void QTrackingTooltip::resizeEvent(QResizeEvent* resizeEvent)
268 if (m_isTracking)
270 SetPosCursorOffset(m_cursorOffset);