emoji_button_factory.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. /*
  2. This file is part of Telegram Desktop,
  3. the official desktop application for the Telegram messaging service.
  4. For license and copyright information please follow this link:
  5. https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
  6. */
  7. #include "ui/controls/emoji_button_factory.h"
  8. #include "base/event_filter.h"
  9. #include "chat_helpers/emoji_suggestions_widget.h"
  10. #include "chat_helpers/message_field.h"
  11. #include "chat_helpers/tabbed_panel.h"
  12. #include "chat_helpers/tabbed_selector.h"
  13. #include "ui/controls/emoji_button.h"
  14. #include "ui/effects/fade_animation.h"
  15. #include "ui/layers/box_content.h"
  16. #include "ui/rect.h"
  17. #include "ui/widgets/fields/input_field.h"
  18. #include "window/window_session_controller.h"
  19. #include "styles/style_chat_helpers.h" // defaultComposeFiles.
  20. #include "styles/style_settings.h"
  21. namespace Ui {
  22. [[nodiscard]] not_null<Ui::EmojiButton*> AddEmojiToggleToField(
  23. not_null<Ui::InputField*> field,
  24. not_null<Ui::BoxContent*> box,
  25. not_null<Window::SessionController*> controller,
  26. not_null<ChatHelpers::TabbedPanel*> emojiPanel,
  27. QPoint shift) {
  28. const auto emojiToggle = Ui::CreateChild<Ui::EmojiButton>(
  29. field->parentWidget(),
  30. st::defaultComposeFiles.emoji);
  31. const auto fade = Ui::CreateChild<Ui::FadeAnimation>(
  32. emojiToggle,
  33. emojiToggle,
  34. 0.5);
  35. {
  36. const auto fadeTarget = Ui::CreateChild<Ui::RpWidget>(emojiToggle);
  37. fadeTarget->resize(emojiToggle->size());
  38. fadeTarget->paintRequest(
  39. ) | rpl::start_with_next([=](const QRect &rect) {
  40. auto p = QPainter(fadeTarget);
  41. if (fade->animating()) {
  42. p.fillRect(fadeTarget->rect(), st::boxBg);
  43. }
  44. fade->paint(p);
  45. }, fadeTarget->lifetime());
  46. rpl::single(false) | rpl::then(
  47. field->focusedChanges()
  48. ) | rpl::start_with_next([=](bool shown) {
  49. if (shown) {
  50. fade->fadeIn(st::universalDuration);
  51. } else {
  52. fade->fadeOut(st::universalDuration);
  53. }
  54. }, emojiToggle->lifetime());
  55. fade->fadeOut(1);
  56. fade->finish();
  57. }
  58. const auto outer = box->getDelegate()->outerContainer();
  59. const auto allow = [](not_null<DocumentData*>) { return true; };
  60. InitMessageFieldHandlers(
  61. controller,
  62. field,
  63. Window::GifPauseReason::Layer,
  64. allow);
  65. Ui::Emoji::SuggestionsController::Init(
  66. outer,
  67. field,
  68. &controller->session(),
  69. Ui::Emoji::SuggestionsController::Options{
  70. .suggestCustomEmoji = true,
  71. .allowCustomWithoutPremium = allow,
  72. });
  73. const auto updateEmojiPanelGeometry = [=] {
  74. const auto parent = emojiPanel->parentWidget();
  75. const auto global = emojiToggle->mapToGlobal({ 0, 0 });
  76. const auto local = parent->mapFromGlobal(global);
  77. const auto right = local.x() + emojiToggle->width() * 3;
  78. const auto isDropDown = local.y() < parent->height() / 2;
  79. emojiPanel->setDropDown(isDropDown);
  80. if (isDropDown) {
  81. emojiPanel->moveTopRight(
  82. local.y() + emojiToggle->height(),
  83. right);
  84. } else {
  85. emojiPanel->moveBottomRight(local.y(), right);
  86. }
  87. };
  88. rpl::combine(
  89. box->sizeValue(),
  90. field->geometryValue()
  91. ) | rpl::start_with_next([=](QSize outer, QRect inner) {
  92. emojiToggle->moveToLeft(
  93. rect::right(inner) + shift.x(),
  94. inner.y() + shift.y());
  95. emojiToggle->update();
  96. }, emojiToggle->lifetime());
  97. emojiToggle->installEventFilter(emojiPanel);
  98. emojiToggle->addClickHandler([=] {
  99. updateEmojiPanelGeometry();
  100. emojiPanel->toggleAnimated();
  101. });
  102. const auto filterCallback = [=](not_null<QEvent*> event) {
  103. if (event->type() == QEvent::Enter) {
  104. updateEmojiPanelGeometry();
  105. }
  106. return base::EventFilterResult::Continue;
  107. };
  108. base::install_event_filter(emojiToggle, filterCallback);
  109. return emojiToggle;
  110. }
  111. } // namespace Ui