| 
									
										
										
										
											2014-05-30 12:53:19 +04:00
										 |  |  | /*
 | 
					
						
							|  |  |  | This file is part of Telegram Desktop, | 
					
						
							| 
									
										
										
										
											2018-01-03 13:23:14 +03:00
										 |  |  | the official desktop application for the Telegram messaging service. | 
					
						
							| 
									
										
										
										
											2014-05-30 12:53:19 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-03 13:23:14 +03:00
										 |  |  | For license and copyright information please follow this link: | 
					
						
							|  |  |  | https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 | 
					
						
							| 
									
										
										
										
											2014-05-30 12:53:19 +04:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2016-11-11 16:46:04 +03:00
										 |  |  | #include "ui/abstract_button.h"
 | 
					
						
							| 
									
										
										
										
											2014-05-30 12:53:19 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-13 15:22:54 +03:00
										 |  |  | #include "ui/ui_utility.h"
 | 
					
						
							| 
									
										
										
										
											2019-09-13 19:45:48 +03:00
										 |  |  | #include "ui/ui_integration.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <QtGui/QtEvents>
 | 
					
						
							| 
									
										
										
										
											2019-09-13 15:22:54 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-01 12:39:07 +03:00
										 |  |  | #include <rpl/filter.h>
 | 
					
						
							|  |  |  | #include <rpl/mappers.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-11 16:46:04 +03:00
										 |  |  | namespace Ui { | 
					
						
							| 
									
										
										
										
											2014-05-30 12:53:19 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-01 12:39:07 +03:00
										 |  |  | AbstractButton::AbstractButton(QWidget *parent) : RpWidget(parent) { | 
					
						
							|  |  |  | 	setMouseTracking(true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	using namespace rpl::mappers; | 
					
						
							|  |  |  | 	shownValue() | 
					
						
							| 
									
										
										
										
											2017-11-20 16:32:55 +04:00
										 |  |  | 		| rpl::filter(_1 == false) | 
					
						
							| 
									
										
										
										
											2017-10-01 12:39:07 +03:00
										 |  |  | 		| rpl::start_with_next([this] { clearState(); }, lifetime()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-11 14:24:37 +03:00
										 |  |  | void AbstractButton::leaveEventHook(QEvent *e) { | 
					
						
							| 
									
										
										
										
											2016-12-05 14:01:08 +03:00
										 |  |  | 	if (_state & StateFlag::Down) return; | 
					
						
							| 
									
										
										
										
											2014-05-30 12:53:19 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-11 16:46:04 +03:00
										 |  |  | 	setOver(false, StateChangeSource::ByHover); | 
					
						
							| 
									
										
										
										
											2017-02-11 14:24:37 +03:00
										 |  |  | 	return TWidget::leaveEventHook(e); | 
					
						
							| 
									
										
										
										
											2014-05-30 12:53:19 +04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-11 14:24:37 +03:00
										 |  |  | void AbstractButton::enterEventHook(QEvent *e) { | 
					
						
							| 
									
										
										
										
											2016-12-05 14:01:08 +03:00
										 |  |  | 	checkIfOver(mapFromGlobal(QCursor::pos())); | 
					
						
							| 
									
										
										
										
											2017-02-11 14:24:37 +03:00
										 |  |  | 	return TWidget::enterEventHook(e); | 
					
						
							| 
									
										
										
										
											2014-05-30 12:53:19 +04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-11 16:46:04 +03:00
										 |  |  | void AbstractButton::setAcceptBoth(bool acceptBoth) { | 
					
						
							| 
									
										
										
										
											2014-05-30 12:53:19 +04:00
										 |  |  | 	_acceptBoth = acceptBoth; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-05 14:01:08 +03:00
										 |  |  | void AbstractButton::checkIfOver(QPoint localPos) { | 
					
						
							|  |  |  | 	auto over = rect().marginsRemoved(getMargins()).contains(localPos); | 
					
						
							|  |  |  | 	setOver(over, StateChangeSource::ByHover); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-11 16:46:04 +03:00
										 |  |  | void AbstractButton::mousePressEvent(QMouseEvent *e) { | 
					
						
							| 
									
										
										
										
											2016-12-05 14:01:08 +03:00
										 |  |  | 	checkIfOver(e->pos()); | 
					
						
							| 
									
										
										
										
											2016-12-02 22:16:35 +03:00
										 |  |  | 	if (_acceptBoth || (e->buttons() & Qt::LeftButton)) { | 
					
						
							| 
									
										
										
										
											2016-12-05 14:01:08 +03:00
										 |  |  | 		if ((_state & StateFlag::Over) && !(_state & StateFlag::Down)) { | 
					
						
							|  |  |  | 			auto was = _state; | 
					
						
							|  |  |  | 			_state |= StateFlag::Down; | 
					
						
							|  |  |  | 			onStateChanged(was, StateChangeSource::ByPress); | 
					
						
							| 
									
										
										
										
											2014-05-30 12:53:19 +04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			e->accept(); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-11 16:46:04 +03:00
										 |  |  | void AbstractButton::mouseMoveEvent(QMouseEvent *e) { | 
					
						
							| 
									
										
										
										
											2016-12-02 22:16:35 +03:00
										 |  |  | 	if (rect().marginsRemoved(getMargins()).contains(e->pos())) { | 
					
						
							| 
									
										
										
										
											2016-11-11 16:46:04 +03:00
										 |  |  | 		setOver(true, StateChangeSource::ByHover); | 
					
						
							| 
									
										
										
										
											2014-05-30 12:53:19 +04:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2016-11-11 16:46:04 +03:00
										 |  |  | 		setOver(false, StateChangeSource::ByHover); | 
					
						
							| 
									
										
										
										
											2014-05-30 12:53:19 +04:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-11 16:46:04 +03:00
										 |  |  | void AbstractButton::mouseReleaseEvent(QMouseEvent *e) { | 
					
						
							| 
									
										
										
										
											2016-12-05 14:01:08 +03:00
										 |  |  | 	if (_state & StateFlag::Down) { | 
					
						
							| 
									
										
										
										
											2018-12-05 13:55:56 +04:00
										 |  |  | 		const auto was = _state; | 
					
						
							| 
									
										
										
										
											2016-12-05 14:01:08 +03:00
										 |  |  | 		_state &= ~State(StateFlag::Down); | 
					
						
							| 
									
										
										
										
											2018-12-05 13:55:56 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-13 19:45:48 +03:00
										 |  |  | 		const auto weak = MakeWeak(this); | 
					
						
							| 
									
										
										
										
											2016-12-05 14:01:08 +03:00
										 |  |  | 		onStateChanged(was, StateChangeSource::ByPress); | 
					
						
							| 
									
										
										
										
											2018-12-05 13:55:56 +04:00
										 |  |  | 		if (!weak) { | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-05 14:01:08 +03:00
										 |  |  | 		if (was & StateFlag::Over) { | 
					
						
							| 
									
										
										
										
											2019-09-13 19:45:48 +03:00
										 |  |  | 			clicked(e->modifiers(), e->button()); | 
					
						
							| 
									
										
										
										
											2014-05-30 12:53:19 +04:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2016-12-05 14:01:08 +03:00
										 |  |  | 			setOver(false, StateChangeSource::ByHover); | 
					
						
							| 
									
										
										
										
											2014-05-30 12:53:19 +04:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-13 19:45:48 +03:00
										 |  |  | void AbstractButton::clicked( | 
					
						
							|  |  |  | 		Qt::KeyboardModifiers modifiers, | 
					
						
							|  |  |  | 		Qt::MouseButton button) { | 
					
						
							|  |  |  | 	_modifiers = modifiers; | 
					
						
							|  |  |  | 	const auto weak = MakeWeak(this); | 
					
						
							|  |  |  | 	if (const auto callback = _clickedCallback) { | 
					
						
							|  |  |  | 		callback(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (weak) { | 
					
						
							|  |  |  | 		_clicks.fire_copy(button); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-31 17:34:41 +04:00
										 |  |  | void AbstractButton::setPointerCursor(bool enablePointerCursor) { | 
					
						
							|  |  |  | 	if (_enablePointerCursor != enablePointerCursor) { | 
					
						
							|  |  |  | 		_enablePointerCursor = enablePointerCursor; | 
					
						
							|  |  |  | 		updateCursor(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-11 16:46:04 +03:00
										 |  |  | void AbstractButton::setOver(bool over, StateChangeSource source) { | 
					
						
							| 
									
										
										
										
											2016-12-05 14:01:08 +03:00
										 |  |  | 	if (over && !(_state & StateFlag::Over)) { | 
					
						
							|  |  |  | 		auto was = _state; | 
					
						
							|  |  |  | 		_state |= StateFlag::Over; | 
					
						
							| 
									
										
										
										
											2019-09-16 14:14:06 +03:00
										 |  |  | 		Integration::Instance().registerLeaveSubscription(this); | 
					
						
							| 
									
										
										
										
											2016-12-05 14:01:08 +03:00
										 |  |  | 		onStateChanged(was, source); | 
					
						
							|  |  |  | 	} else if (!over && (_state & StateFlag::Over)) { | 
					
						
							|  |  |  | 		auto was = _state; | 
					
						
							|  |  |  | 		_state &= ~State(StateFlag::Over); | 
					
						
							| 
									
										
										
										
											2019-09-16 14:14:06 +03:00
										 |  |  | 		Integration::Instance().unregisterLeaveSubscription(this); | 
					
						
							| 
									
										
										
										
											2016-12-05 14:01:08 +03:00
										 |  |  | 		onStateChanged(was, source); | 
					
						
							| 
									
										
										
										
											2014-09-28 19:47:30 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-12-31 17:34:41 +04:00
										 |  |  | 	updateCursor(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AbstractButton::updateCursor() { | 
					
						
							|  |  |  | 	auto pointerCursor = _enablePointerCursor && (_state & StateFlag::Over); | 
					
						
							|  |  |  | 	setCursor(pointerCursor ? style::cur_pointer : style::cur_default); | 
					
						
							| 
									
										
										
										
											2014-09-28 19:47:30 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-11 16:46:04 +03:00
										 |  |  | void AbstractButton::setDisabled(bool disabled) { | 
					
						
							| 
									
										
										
										
											2016-12-05 14:01:08 +03:00
										 |  |  | 	auto was = _state; | 
					
						
							|  |  |  | 	if (disabled && !(_state & StateFlag::Disabled)) { | 
					
						
							|  |  |  | 		_state |= StateFlag::Disabled; | 
					
						
							|  |  |  | 		onStateChanged(was, StateChangeSource::ByUser); | 
					
						
							|  |  |  | 	} else if (!disabled && (_state & StateFlag::Disabled)) { | 
					
						
							|  |  |  | 		_state &= ~State(StateFlag::Disabled); | 
					
						
							|  |  |  | 		onStateChanged(was, StateChangeSource::ByUser); | 
					
						
							| 
									
										
										
										
											2014-05-30 12:53:19 +04:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-11 16:46:04 +03:00
										 |  |  | void AbstractButton::clearState() { | 
					
						
							| 
									
										
										
										
											2016-12-05 14:01:08 +03:00
										 |  |  | 	auto was = _state; | 
					
						
							|  |  |  | 	_state = StateFlag::None; | 
					
						
							|  |  |  | 	onStateChanged(was, StateChangeSource::ByUser); | 
					
						
							| 
									
										
										
										
											2014-05-30 12:53:19 +04:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2016-11-11 16:46:04 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | } // namespace Ui
 |