lib_ui/ui/widgets/menu/menu_item_base.cpp

215 lines
4.5 KiB
C++

// This file is part of Desktop App Toolkit,
// a set of libraries for developing nice desktop applications.
//
// For license and copyright information please follow this link:
// https://github.com/desktop-app/legal/blob/master/LEGAL
//
#include "ui/widgets/menu/menu_item_base.h"
#include "ui/widgets/menu/menu.h"
namespace Ui::Menu {
ItemBase::ItemBase(
not_null<Menu*> parent,
const style::Menu &st)
: RippleButton(parent, st.ripple)
, _menu(parent) {
}
void ItemBase::setSelected(
bool selected,
TriggeredSource source) {
if (selected && !isEnabled()) {
return;
}
if (_selected.current() != selected) {
setMouseTracking(!selected);
_lastTriggeredSource = source;
_selected = selected;
update();
if (selected && focusPolicy() != Qt::NoFocus) {
setFocus();
QAccessibleEvent event(this, QAccessible::Focus);
QAccessible::updateAccessibility(&event);
}
}
}
bool ItemBase::isSelected() const {
return _selected.current();
}
rpl::producer<CallbackData> ItemBase::selects() const {
return _selected.changes(
) | rpl::map([=](bool selected) -> CallbackData {
return {
action(),
y(),
_lastTriggeredSource,
_index,
selected,
_preventClose,
};
});
}
TriggeredSource ItemBase::lastTriggeredSource() const {
return _lastTriggeredSource;
}
int ItemBase::index() const {
return _index;
}
void ItemBase::setIndex(int index) {
_index = index;
}
void ItemBase::setClicked(TriggeredSource source) {
if (isEnabled()) {
_lastTriggeredSource = source;
_clicks.fire({});
}
}
rpl::producer<CallbackData> ItemBase::clicks() const {
return rpl::merge(
AbstractButton::clicks() | rpl::to_empty,
_clicks.events()
) | rpl::filter([=] {
return isEnabled() && !AbstractButton::isDisabled();
}) | rpl::map([=]() -> CallbackData {
return {
action(),
y(),
_lastTriggeredSource,
_index,
true,
_preventClose,
};
});
}
rpl::producer<int> ItemBase::minWidthValue() const {
return _minWidth.value();
}
int ItemBase::minWidth() const {
return _minWidth.current();
}
void ItemBase::fitToMenuWidth() {
_menu->widthValue() | rpl::on_next([=](int w) {
if (w > 0) {
resize(w, contentHeight());
}
}, lifetime());
}
void ItemBase::setMinWidth(int w) {
_minWidth = w;
}
void ItemBase::setPreventClose(bool prevent) {
_preventClose = prevent;
}
bool ItemBase::preventClose() const {
return _preventClose;
}
void ItemBase::finishAnimating() {
RippleButton::finishAnimating();
}
void ItemBase::enableMouseSelecting() {
enableMouseSelecting(this);
}
void ItemBase::enableMouseSelecting(not_null<RpWidget*> widget) {
widget->events(
) | rpl::on_next([=](not_null<QEvent*> e) {
const auto type = e->type();
if (((type == QEvent::Leave)
|| (type == QEvent::Enter)
|| (type == QEvent::MouseMove)) && action()->isEnabled()) {
setSelected(e->type() != QEvent::Leave);
} else if ((type == QEvent::MouseButtonRelease)
&& isEnabled()
&& isSelected()) {
const auto point = mapFromGlobal(QCursor::pos());
if (!rect().contains(point)) {
setSelected(false);
}
}
}, lifetime());
}
void ItemBase::setActionTriggered(Fn<void()> callback) {
if (callback) {
_connection = QObject::connect(
action(),
&QAction::triggered,
std::move(callback));
} else {
_connection.reset();
}
}
void ItemBase::keyPressEvent(QKeyEvent *e) {
e->ignore();
}
void ItemBase::keyReleaseEvent(QKeyEvent *e) {
e->ignore();
}
void ItemBase::mousePressEvent(QMouseEvent *e) {
if (!_menu->hasMouseMoved(e->globalPos())) {
return;
}
if (e->button() == Qt::LeftButton) {
_mousePressed = true;
}
RippleButton::mousePressEvent(e);
}
void ItemBase::mouseMoveEvent(QMouseEvent *e) {
_menu->mouseMoved();
if (!_menu->hasMouseMoved(e->globalPos())) {
return;
}
if (_mousePressed && _menu && !rect().contains(e->pos())) {
_menu->handlePressedOutside(e->globalPos());
}
RippleButton::mouseMoveEvent(e);
}
void ItemBase::mouseReleaseEvent(QMouseEvent *e) {
if (!_menu->hasMouseMoved(e->globalPos())) {
return;
}
const auto wasPressed = base::take(_mousePressed);
#ifdef Q_OS_UNIX
if (isEnabled() && e->button() == Qt::RightButton) {
setClicked(TriggeredSource::Mouse);
return;
}
#endif // Q_OS_UNIX
const auto isInRect = rect().contains(e->pos());
if (isInRect
&& isEnabled()
&& e->button() == Qt::LeftButton
&& !wasPressed) {
//
setClicked(TriggeredSource::Mouse);
return;
}
if (wasPressed && _menu && !isInRect) {
_menu->handleMouseRelease(e->globalPos());
}
RippleButton::mouseReleaseEvent(e);
}
} // namespace Ui::Menu