From 6ae122f1b27332a27316892dada6050e2f225ad8 Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 3 Jun 2022 18:05:09 +0400 Subject: [PATCH] Move Ui::Menu::MenuCallback and st::menuWithIcons here. --- CMakeLists.txt | 4 ++ ui/layers/layers.style | 9 +++ ui/widgets/menu/menu_add_action_callback.cpp | 29 +++++++++ ui/widgets/menu/menu_add_action_callback.h | 41 ++++++++++++ .../menu/menu_add_action_callback_factory.cpp | 46 ++++++++++++++ .../menu/menu_add_action_callback_factory.h | 23 +++++++ ui/widgets/separate_panel.cpp | 62 ++++++++++++++++++- ui/widgets/separate_panel.h | 16 ++++- ui/widgets/widgets.style | 26 ++++++++ 9 files changed, 250 insertions(+), 6 deletions(-) create mode 100644 ui/widgets/menu/menu_add_action_callback.cpp create mode 100644 ui/widgets/menu/menu_add_action_callback.h create mode 100644 ui/widgets/menu/menu_add_action_callback_factory.cpp create mode 100644 ui/widgets/menu/menu_add_action_callback_factory.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 6d1ddab..82084a3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -188,6 +188,10 @@ PRIVATE ui/widgets/menu/menu.h ui/widgets/menu/menu_action.cpp ui/widgets/menu/menu_action.h + ui/widgets/menu/menu_add_action_callback.cpp + ui/widgets/menu/menu_add_action_callback.h + ui/widgets/menu/menu_add_action_callback_factory.cpp + ui/widgets/menu/menu_add_action_callback_factory.h ui/widgets/menu/menu_common.cpp ui/widgets/menu/menu_common.h ui/widgets/menu/menu_item_base.cpp diff --git a/ui/layers/layers.style b/ui/layers/layers.style index 75675c1..b8824e9 100644 --- a/ui/layers/layers.style +++ b/ui/layers/layers.style @@ -170,6 +170,15 @@ separatePanelClose: IconButton(boxTitleClose) { color: windowBgOver; } } +separatePanelMenu: IconButton(separatePanelClose) { + width: 44px; + + icon: icon {{ "title_menu_dots", boxTitleCloseFg }}; + iconOver: icon {{ "title_menu_dots", boxTitleCloseFgOver }}; + + rippleAreaPosition: point(0px, 8px); +} +separatePanelMenuPosition: point(0px, 52px); separatePanelTitleFont: font(18px semibold); separatePanelTitle: FlatLabel(defaultFlatLabel) { textFg: boxTitleFg; diff --git a/ui/widgets/menu/menu_add_action_callback.cpp b/ui/widgets/menu/menu_add_action_callback.cpp new file mode 100644 index 0000000..81a9acb --- /dev/null +++ b/ui/widgets/menu/menu_add_action_callback.cpp @@ -0,0 +1,29 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#include "ui/widgets/menu/menu_add_action_callback.h" + +#include "ui/style/style_core.h" + +namespace Ui::Menu { + +MenuCallback::MenuCallback(MenuCallback::Callback callback) +: _callback(std::move(callback)) { +} + +QAction *MenuCallback::operator()(Args &&args) const { + return _callback(std::move(args)); +} + +QAction *MenuCallback::operator()( + const QString &text, + Fn handler, + const style::icon *icon) const { + return _callback({ text, std::move(handler), icon, nullptr }); +} + +} // namespace Ui::Menu diff --git a/ui/widgets/menu/menu_add_action_callback.h b/ui/widgets/menu/menu_add_action_callback.h new file mode 100644 index 0000000..368c066 --- /dev/null +++ b/ui/widgets/menu/menu_add_action_callback.h @@ -0,0 +1,41 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#pragma once + +#include "ui/style/style_core.h" + +namespace Ui { +class PopupMenu; +} // namespace Ui + +namespace Ui::Menu { + +struct MenuCallback final { +public: + struct Args { + QString text; + Fn handler; + const style::icon *icon; + Fn)> fillSubmenu; + bool isSeparator = false; + bool isAttention = false; + }; + using Callback = Fn; + + explicit MenuCallback(Callback callback); + + QAction *operator()(Args &&args) const; + QAction *operator()( + const QString &text, + Fn handler, + const style::icon *icon) const; +private: + Callback _callback; +}; + +} // namespace Ui::Menu diff --git a/ui/widgets/menu/menu_add_action_callback_factory.cpp b/ui/widgets/menu/menu_add_action_callback_factory.cpp new file mode 100644 index 0000000..443fa45 --- /dev/null +++ b/ui/widgets/menu/menu_add_action_callback_factory.cpp @@ -0,0 +1,46 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#include "ui/widgets/menu/menu_add_action_callback_factory.h" + +#include "ui/widgets/menu/menu_add_action_callback.h" +#include "ui/widgets/menu/menu_action.h" +#include "ui/widgets/popup_menu.h" +#include "styles/style_widgets.h" + +namespace Ui::Menu { + +MenuCallback CreateAddActionCallback( + const base::unique_qptr &menu) { + return MenuCallback([&](MenuCallback::Args a) { + if (a.fillSubmenu) { + const auto action = menu->addAction( + a.text, + std::move(a.handler), + a.icon); + // Dummy menu. + action->setMenu(Ui::CreateChild(menu->menu().get())); + a.fillSubmenu(menu->ensureSubmenu(action)); + return action; + } else if (a.isSeparator) { + return menu->addSeparator(); + } else if (a.isAttention) { + return menu->addAction(base::make_unique_q( + menu, + st::menuWithIconsAttention, + Ui::Menu::CreateAction( + menu->menu().get(), + a.text, + std::move(a.handler)), + a.icon, + a.icon)); + } + return menu->addAction(a.text, std::move(a.handler), a.icon); + }); +} + +} // namespace Ui::Menu diff --git a/ui/widgets/menu/menu_add_action_callback_factory.h b/ui/widgets/menu/menu_add_action_callback_factory.h new file mode 100644 index 0000000..3d9b37a --- /dev/null +++ b/ui/widgets/menu/menu_add_action_callback_factory.h @@ -0,0 +1,23 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#pragma once + +#include "base/unique_qptr.h" + +namespace Ui { +class PopupMenu; +} // namespace Ui + +namespace Ui::Menu { + +struct MenuCallback; + +[[nodiscard]] MenuCallback CreateAddActionCallback( + const base::unique_qptr &menu); + +} // namespace Ui::Menu diff --git a/ui/widgets/separate_panel.cpp b/ui/widgets/separate_panel.cpp index 8f916ea..893c287 100644 --- a/ui/widgets/separate_panel.cpp +++ b/ui/widgets/separate_panel.cpp @@ -10,16 +10,19 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/shadow.h" #include "ui/widgets/buttons.h" #include "ui/widgets/labels.h" +#include "ui/widgets/tooltip.h" +#include "ui/widgets/popup_menu.h" +#include "ui/widgets/menu/menu_add_action_callback.h" +#include "ui/widgets/menu/menu_add_action_callback_factory.h" #include "ui/wrap/padding_wrap.h" #include "ui/wrap/fade_wrap.h" #include "ui/toasts/common_toasts.h" -#include "ui/widgets/tooltip.h" #include "ui/platform/ui_platform_utility.h" #include "ui/layers/layer_widget.h" +#include "base/debug_log.h" #include "styles/style_widgets.h" #include "styles/style_layers.h" #include "styles/palette.h" -#include "base/debug_log.h" #include #include @@ -70,7 +73,8 @@ void SeparatePanel::initControls() { void SeparatePanel::updateTitleGeometry(int newWidth) { _title->resizeToWidth(newWidth - _padding.left() - _back->width() - - _padding.right() - _close->width()); + - _padding.right() - _close->width() + - (_menuToggle ? _menuToggle->width() : 0)); updateTitlePosition(); } @@ -110,6 +114,58 @@ void SeparatePanel::setBackAllowed(bool allowed) { } } +void SeparatePanel::setMenuAllowed( + Fn fill) { + _menuToggle.create(this, st::separatePanelMenu); + _menuToggle->show(); + _menuToggle->setClickedCallback([=] { showMenu(fill); }); + + widthValue( + ) | rpl::start_with_next([=](int width) { + _menuToggle->moveToRight( + _padding.right() + _close->width(), + _padding.top()); + }, _menuToggle->lifetime()); +} + +void SeparatePanel::showMenu(Fn fill) { + const auto created = createMenu(_menuToggle); + if (!created) { + return; + } + fill(Menu::CreateAddActionCallback(_menu)); + if (_menu->empty()) { + _menu = nullptr; + } else { + _menu->setForcedOrigin(PanelAnimation::Origin::TopRight); + _menu->popup(mapToGlobal(QPoint( + (width() + - _padding.right() + - _close->width() + + st::separatePanelMenuPosition.x()), + st::separatePanelMenuPosition.y()))); + } +} + +bool SeparatePanel::createMenu(not_null button) { + if (_menu) { + return false; + } + _menu = base::make_unique_q(this, st::popupMenuWithIcons); + _menu->setDestroyedCallback([ + weak = Ui::MakeWeak(this), + weakButton = Ui::MakeWeak(button), + menu = _menu.get()]{ + if (weak && weak->_menu == menu) { + if (weakButton) { + weakButton->setForceRippled(false); + } + } + }); + button->setForceRippled(true); + return true; +} + void SeparatePanel::setHideOnDeactivate(bool hideOnDeactivate) { _hideOnDeactivate = hideOnDeactivate; if (!_hideOnDeactivate) { diff --git a/ui/widgets/separate_panel.h b/ui/widgets/separate_panel.h index 6758be3..5432b33 100644 --- a/ui/widgets/separate_panel.h +++ b/ui/widgets/separate_panel.h @@ -14,16 +14,19 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL class Painter; +namespace Ui::Menu { +struct MenuCallback; +} // namespace Ui::Menu + namespace Ui { + class BoxContent; class IconButton; +class PopupMenu; class LayerStackWidget; class FlatLabel; template class FadeWrapScaled; -} // namespace Ui - -namespace Ui { class SeparatePanel final : public RpWidget { public: @@ -50,6 +53,8 @@ public: [[nodiscard]] rpl::producer<> closeEvents() const; void setBackAllowed(bool allowed); + void setMenuAllowed(Fn fill); + protected: void paintEvent(QPaintEvent *e) override; void closeEvent(QCloseEvent *e) override; @@ -83,12 +88,17 @@ private: void finishAnimating(); void finishClose(); + void showMenu(Fn fill); + [[nodiscard]] bool createMenu(not_null button); + object_ptr _close; + object_ptr _menuToggle = { nullptr }; object_ptr _title = { nullptr }; object_ptr> _back; object_ptr _body; base::unique_qptr _inner; base::unique_qptr _layer = { nullptr }; + base::unique_qptr _menu; rpl::event_stream<> _synteticBackRequests; rpl::event_stream<> _userCloseRequests; rpl::event_stream<> _closeEvents; diff --git a/ui/widgets/widgets.style b/ui/widgets/widgets.style index ac33b07..230f529 100644 --- a/ui/widgets/widgets.style +++ b/ui/widgets/widgets.style @@ -1567,3 +1567,29 @@ sideBarButtonLockBlockHeight: 5px; sideBarButtonLockLineHeight: 1px; sideBarButtonLockPenWidth: 3px; sideBarButtonLockPenWidthDivider: 2; + +menuIconColor: windowBoldFg; +menuIconAttentionColor: attentionButtonFg; + +menuIconSubmenuArrow: icon {{ "menu/submenu_arrow", menuIconColor }}; + +menuWithIcons: Menu(defaultMenu) { + itemIconPosition: point(15px, 5px); + itemPadding: margins(54px, 8px, 17px, 8px); + + arrow: menuIconSubmenuArrow; +} +menuWithIconsAttention: Menu(menuWithIcons) { + itemFg: attentionButtonFg; + itemFgOver: attentionButtonFgOver; +} +popupMenuWithIcons: PopupMenu(defaultPopupMenu) { + scrollPadding: margins(0px, 5px, 0px, 5px); + menu: menuWithIcons; +} +dropdownMenuWithIcons: DropdownMenu(defaultDropdownMenu) { + wrap: InnerDropdown(defaultInnerDropdown) { + scrollPadding: margins(0px, 5px, 0px, 5px); + } + menu: menuWithIcons; +}