| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280 |
- /*
- 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/chat/pinned_bar.h"
- #include "ui/chat/message_bar.h"
- #include "ui/effects/spoiler_mess.h"
- #include "ui/widgets/shadow.h"
- #include "ui/widgets/buttons.h"
- #include "ui/wrap/fade_wrap.h"
- #include "styles/style_chat_helpers.h"
- #include "styles/palette.h"
- #include <QtGui/QtEvents>
- namespace Ui {
- PinnedBar::PinnedBar(
- not_null<QWidget*> parent,
- Fn<bool()> customEmojiPaused,
- rpl::producer<> customEmojiPausedChanges)
- : _wrap(parent, object_ptr<RpWidget>(parent))
- , _shadow(std::make_unique<PlainShadow>(_wrap.parentWidget()))
- , _customEmojiPaused(std::move(customEmojiPaused)) {
- _wrap.hide(anim::type::instant);
- _shadow->hide();
- _shadow->showOn(rpl::combine(
- _wrap.shownValue(),
- _wrap.heightValue(),
- rpl::mappers::_1 && rpl::mappers::_2 > 0
- ) | rpl::filter([=](bool shown) {
- return (shown == _shadow->isHidden());
- }));
- _wrap.entity()->paintRequest(
- ) | rpl::start_with_next([=](QRect clip) {
- QPainter(_wrap.entity()).fillRect(clip, st::historyPinnedBg);
- }, lifetime());
- _wrap.setAttribute(Qt::WA_OpaquePaintEvent);
- if (customEmojiPausedChanges) {
- std::move(
- customEmojiPausedChanges
- ) | rpl::start_with_next([=] {
- _wrap.entity()->update();
- }, lifetime());
- }
- }
- PinnedBar::~PinnedBar() {
- _right.button.destroy();
- }
- void PinnedBar::setContent(rpl::producer<Ui::MessageBarContent> content) {
- _contentLifetime.destroy();
- auto copy = std::move(
- content
- ) | rpl::start_spawning(_contentLifetime);
- rpl::duplicate(
- copy
- ) | rpl::filter([=](const MessageBarContent &content) {
- return !content.title.isEmpty() || !content.text.text.isEmpty();
- }) | rpl::start_with_next([=](MessageBarContent &&content) {
- const auto creating = !_bar;
- if (creating) {
- createControls();
- }
- // In most cases the new right button should arrive
- // before we want to get its width.
- const auto right = _right.button ? _right.button->width() : 0;
- content.margins = { 0, 0, right, 0 };
- _bar->set(std::move(content));
- if (creating) {
- _bar->finishAnimating();
- }
- }, _contentLifetime);
- std::move(
- copy
- ) | rpl::map([=](const MessageBarContent &content) {
- return content.title.isEmpty() || content.text.text.isEmpty();
- }) | rpl::start_with_next_done([=](bool hidden) {
- _shouldBeShown = !hidden;
- if (!_forceHidden) {
- _wrap.toggle(_shouldBeShown, anim::type::normal);
- } else if (!_shouldBeShown) {
- _bar = nullptr;
- }
- }, [=] {
- _forceHidden = true;
- _wrap.toggle(false, anim::type::normal);
- }, _contentLifetime);
- }
- void PinnedBar::setRightButton(object_ptr<Ui::RpWidget> button) {
- const auto hasPrevious = (_right.button != nullptr);
- if (auto previous = _right.button.release()) {
- using Unique = base::unique_qptr<Ui::FadeWrapScaled<Ui::RpWidget>>;
- _right.previousButtonLifetime = previous->shownValue(
- ) | rpl::filter(!rpl::mappers::_1) | rpl::start_with_next([=] {
- _right.previousButtonLifetime.destroy();
- });
- previous->hide(anim::type::normal);
- _right.previousButtonLifetime.make_state<Unique>(Unique{ previous });
- }
- _right.button.create(_wrap.entity(), std::move(button));
- if (_right.button) {
- _right.button->setParent(_wrap.entity());
- if (hasPrevious) {
- _right.button->setDuration(st::defaultMessageBar.duration);
- _right.button->show(anim::type::normal);
- } else {
- _right.button->setDuration(0);
- _right.button->show(anim::type::instant);
- }
- }
- if (_bar) {
- updateControlsGeometry(_wrap.geometry());
- }
- }
- void PinnedBar::updateControlsGeometry(QRect wrapGeometry) {
- _bar->widget()->resizeToWidth(wrapGeometry.width());
- if (_right.button) {
- _right.button->moveToRight(0, 0);
- }
- }
- void PinnedBar::setShadowGeometryPostprocess(Fn<QRect(QRect)> postprocess) {
- _shadowGeometryPostprocess = std::move(postprocess);
- updateShadowGeometry(_wrap.geometry());
- }
- void PinnedBar::updateShadowGeometry(QRect wrapGeometry) {
- const auto regular = QRect(
- wrapGeometry.x(),
- wrapGeometry.y() + wrapGeometry.height(),
- wrapGeometry.width(),
- st::lineWidth);
- _shadow->setGeometry(_shadowGeometryPostprocess
- ? _shadowGeometryPostprocess(regular)
- : regular);
- }
- void PinnedBar::createControls() {
- Expects(!_bar);
- _bar = std::make_unique<MessageBar>(
- _wrap.entity(),
- st::defaultMessageBar,
- _customEmojiPaused);
- if (_right.button) {
- _right.button->raise();
- }
- // Clicks.
- _bar->widget()->setCursor(style::cur_pointer);
- _bar->widget()->events(
- ) | rpl::filter([=](not_null<QEvent*> event) {
- return (event->type() == QEvent::MouseButtonPress)
- && (static_cast<QMouseEvent*>(event.get())->button()
- == Qt::LeftButton);
- }) | rpl::map([=] {
- return _bar->widget()->events(
- ) | rpl::filter([](not_null<QEvent*> event) {
- return (event->type() == QEvent::MouseButtonRelease);
- }) | rpl::take(1) | rpl::filter([=](not_null<QEvent*> event) {
- return _bar->widget()->rect().contains(
- static_cast<QMouseEvent*>(event.get())->pos());
- });
- }) | rpl::flatten_latest(
- ) | rpl::to_empty | rpl::start_to_stream(
- _barClicks,
- _bar->widget()->lifetime());
- _bar->widget()->move(0, 0);
- _bar->widget()->show();
- _wrap.entity()->resize(
- _wrap.entity()->width(),
- _bar->widget()->height());
- _wrap.geometryValue(
- ) | rpl::start_with_next([=](QRect rect) {
- updateShadowGeometry(rect);
- updateControlsGeometry(rect);
- }, _bar->widget()->lifetime());
- _wrap.shownValue(
- ) | rpl::skip(
- 1
- ) | rpl::filter([=](bool shown) {
- return !shown && !_forceHidden;
- }) | rpl::start_with_next([=] {
- _bar = nullptr;
- }, _bar->widget()->lifetime());
- Ensures(_bar != nullptr);
- }
- void PinnedBar::show() {
- if (!_forceHidden) {
- return;
- }
- _forceHidden = false;
- if (_shouldBeShown) {
- _wrap.show(anim::type::instant);
- } else if (!_wrap.isHidden() && !_wrap.animating()) {
- _wrap.hide(anim::type::instant);
- }
- }
- void PinnedBar::hide() {
- if (_forceHidden) {
- return;
- }
- _forceHidden = true;
- _wrap.hide(anim::type::instant);
- }
- void PinnedBar::raise() {
- _wrap.raise();
- _shadow->raise();
- }
- void PinnedBar::customEmojiRepaint() {
- if (_bar) {
- _bar->customEmojiRepaint();
- }
- }
- void PinnedBar::finishAnimating() {
- _wrap.finishAnimating();
- }
- void PinnedBar::move(int x, int y) {
- _wrap.move(x, y);
- }
- void PinnedBar::resizeToWidth(int width) {
- _wrap.entity()->resizeToWidth(width);
- }
- int PinnedBar::height() const {
- return !_forceHidden
- ? _wrap.height()
- : _shouldBeShown
- ? st::historyReplyHeight
- : 0;
- }
- rpl::producer<int> PinnedBar::heightValue() const {
- return _wrap.heightValue();
- }
- rpl::producer<> PinnedBar::barClicks() const {
- return _barClicks.events();
- }
- rpl::producer<> PinnedBar::contextMenuRequested() const {
- return _wrap.entity()->paintRequest(
- ) | rpl::filter([=] {
- return _bar && _bar->widget();
- }) | rpl::map([=] {
- return _bar->widget()->events(
- ) | rpl::filter([](not_null<QEvent*> event) {
- return (event->type() == QEvent::ContextMenu);
- }) | rpl::to_empty;
- }) | rpl::flatten_latest();
- }
- } // namespace Ui
|