more_chats_bar.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  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/chat/more_chats_bar.h"
  8. #include "ui/widgets/buttons.h"
  9. #include "ui/widgets/shadow.h"
  10. #include "ui/text/text_options.h"
  11. #include "ui/painter.h"
  12. #include "lang/lang_keys.h"
  13. #include "styles/style_chat_helpers.h"
  14. #include "styles/style_window.h" // st::columnMinimalWidthLeft
  15. namespace Ui {
  16. MoreChatsBar::MoreChatsBar(
  17. not_null<QWidget*> parent,
  18. rpl::producer<MoreChatsBarContent> content)
  19. : _wrap(parent, object_ptr<RpWidget>(parent))
  20. , _inner(_wrap.entity())
  21. , _shadow(std::make_unique<PlainShadow>(_wrap.parentWidget()))
  22. , _close(_inner.get(), st::moreChatsBarClose) {
  23. _wrap.hide(anim::type::instant);
  24. _shadow->hide();
  25. _wrap.entity()->paintRequest(
  26. ) | rpl::start_with_next([=](QRect clip) {
  27. QPainter(_wrap.entity()).fillRect(clip, st::historyPinnedBg);
  28. }, lifetime());
  29. _wrap.setAttribute(Qt::WA_OpaquePaintEvent);
  30. auto copy = std::move(
  31. content
  32. ) | rpl::start_spawning(_wrap.lifetime());
  33. rpl::duplicate(
  34. copy
  35. ) | rpl::start_with_next([=](MoreChatsBarContent &&content) {
  36. _content = content;
  37. if (_content.count > 0) {
  38. _text.setText(
  39. st::defaultMessageBar.title,
  40. tr::lng_filters_bar_you_can(
  41. tr::now,
  42. lt_count,
  43. _content.count),
  44. Ui::NameTextOptions());
  45. _status.setText(
  46. st::defaultMessageBar.text,
  47. tr::lng_filters_bar_view(
  48. tr::now,
  49. lt_count,
  50. _content.count),
  51. Ui::NameTextOptions());
  52. }
  53. _inner->update();
  54. }, lifetime());
  55. std::move(
  56. copy
  57. ) | rpl::map([=](const MoreChatsBarContent &content) {
  58. return !content.count;
  59. }) | rpl::start_with_next_done([=](bool hidden) {
  60. _shouldBeShown = !hidden;
  61. if (!_forceHidden) {
  62. _wrap.toggle(_shouldBeShown, anim::type::normal);
  63. }
  64. }, [=] {
  65. _forceHidden = true;
  66. _wrap.toggle(false, anim::type::normal);
  67. }, lifetime());
  68. setupInner();
  69. }
  70. MoreChatsBar::~MoreChatsBar() = default;
  71. void MoreChatsBar::setupInner() {
  72. _inner->resize(0, st::moreChatsBarHeight);
  73. _inner->paintRequest(
  74. ) | rpl::start_with_next([=](QRect rect) {
  75. auto p = Painter(_inner);
  76. paint(p);
  77. }, _inner->lifetime());
  78. // Clicks.
  79. _inner->setCursor(style::cur_pointer);
  80. _inner->events(
  81. ) | rpl::filter([=](not_null<QEvent*> event) {
  82. return (event->type() == QEvent::MouseButtonPress);
  83. }) | rpl::map([=] {
  84. return _inner->events(
  85. ) | rpl::filter([=](not_null<QEvent*> event) {
  86. return (event->type() == QEvent::MouseButtonRelease);
  87. }) | rpl::take(1) | rpl::filter([=](not_null<QEvent*> event) {
  88. return _inner->rect().contains(
  89. static_cast<QMouseEvent*>(event.get())->pos());
  90. });
  91. }) | rpl::flatten_latest(
  92. ) | rpl::to_empty | rpl::start_to_stream(_barClicks, _inner->lifetime());
  93. _wrap.geometryValue(
  94. ) | rpl::start_with_next([=](QRect rect) {
  95. updateShadowGeometry(rect);
  96. updateControlsGeometry(rect);
  97. }, _inner->lifetime());
  98. }
  99. void MoreChatsBar::paint(Painter &p) {
  100. p.fillRect(_inner->rect(), st::historyComposeAreaBg);
  101. const auto width = std::max(
  102. _inner->width(),
  103. st::columnMinimalWidthLeft);
  104. const auto available = width
  105. - st::moreChatsBarTextPosition.x()
  106. - st::moreChatsBarClose.width;
  107. p.setPen(st::defaultMessageBar.titleFg);
  108. _text.drawElided(
  109. p,
  110. st::moreChatsBarTextPosition.x(),
  111. st::moreChatsBarTextPosition.y(),
  112. available);
  113. p.setPen(st::defaultMessageBar.textFg);
  114. _status.drawElided(
  115. p,
  116. st::moreChatsBarStatusPosition.x(),
  117. st::moreChatsBarStatusPosition.y(),
  118. available);
  119. }
  120. void MoreChatsBar::updateControlsGeometry(QRect wrapGeometry) {
  121. const auto hidden = _wrap.isHidden() || !wrapGeometry.height();
  122. if (_shadow->isHidden() != hidden) {
  123. _shadow->setVisible(!hidden);
  124. }
  125. const auto width = std::max(
  126. wrapGeometry.width(),
  127. st::columnMinimalWidthLeft);
  128. _close->move(width - _close->width(), 0);
  129. }
  130. void MoreChatsBar::setShadowGeometryPostprocess(Fn<QRect(QRect)> postprocess) {
  131. _shadowGeometryPostprocess = std::move(postprocess);
  132. updateShadowGeometry(_wrap.geometry());
  133. }
  134. void MoreChatsBar::updateShadowGeometry(QRect wrapGeometry) {
  135. const auto regular = QRect(
  136. wrapGeometry.x(),
  137. wrapGeometry.y() + wrapGeometry.height(),
  138. wrapGeometry.width(),
  139. st::lineWidth);
  140. _shadow->setGeometry(_shadowGeometryPostprocess
  141. ? _shadowGeometryPostprocess(regular)
  142. : regular);
  143. }
  144. void MoreChatsBar::show() {
  145. if (!_forceHidden) {
  146. return;
  147. }
  148. _forceHidden = false;
  149. if (_shouldBeShown) {
  150. _wrap.show(anim::type::instant);
  151. _shadow->show();
  152. }
  153. }
  154. void MoreChatsBar::hide() {
  155. if (_forceHidden) {
  156. return;
  157. }
  158. _forceHidden = true;
  159. _wrap.hide(anim::type::instant);
  160. _shadow->hide();
  161. }
  162. void MoreChatsBar::raise() {
  163. _wrap.raise();
  164. _shadow->raise();
  165. }
  166. void MoreChatsBar::finishAnimating() {
  167. _wrap.finishAnimating();
  168. }
  169. void MoreChatsBar::move(int x, int y) {
  170. _wrap.move(x, y);
  171. }
  172. void MoreChatsBar::resizeToWidth(int width) {
  173. _wrap.entity()->resizeToWidth(width);
  174. _inner->resizeToWidth(width);
  175. }
  176. int MoreChatsBar::height() const {
  177. return !_forceHidden
  178. ? _wrap.height()
  179. : _shouldBeShown
  180. ? st::moreChatsBarHeight
  181. : 0;
  182. }
  183. rpl::producer<int> MoreChatsBar::heightValue() const {
  184. return _wrap.heightValue();
  185. }
  186. rpl::producer<> MoreChatsBar::barClicks() const {
  187. return _barClicks.events();
  188. }
  189. rpl::producer<> MoreChatsBar::closeClicks() const {
  190. return _close->clicks() | rpl::to_empty;
  191. }
  192. } // namespace Ui