"Fossies" - the Fresh Open Source Software Archive

Member "tdesktop-2.6.1/Telegram/SourceFiles/ui/chat/pinned_bar.cpp" (24 Feb 2021, 5255 Bytes) of package /linux/misc/tdesktop-2.6.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "pinned_bar.cpp" see the Fossies "Dox" file reference documentation.

    1 /*
    2 This file is part of Telegram Desktop,
    3 the official desktop application for the Telegram messaging service.
    4 
    5 For license and copyright information please follow this link:
    6 https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
    7 */
    8 #include "ui/chat/pinned_bar.h"
    9 
   10 #include "ui/chat/message_bar.h"
   11 #include "ui/widgets/shadow.h"
   12 #include "ui/widgets/buttons.h"
   13 #include "styles/style_chat.h"
   14 #include "styles/palette.h"
   15 
   16 #include <QtGui/QtEvents>
   17 
   18 namespace Ui {
   19 
   20 PinnedBar::PinnedBar(
   21     not_null<QWidget*> parent,
   22     rpl::producer<MessageBarContent> content)
   23 : _wrap(parent, object_ptr<RpWidget>(parent))
   24 , _shadow(std::make_unique<PlainShadow>(_wrap.parentWidget())) {
   25     _wrap.hide(anim::type::instant);
   26     _shadow->hide();
   27 
   28     _wrap.entity()->paintRequest(
   29     ) | rpl::start_with_next([=](QRect clip) {
   30         QPainter(_wrap.entity()).fillRect(clip, st::historyPinnedBg);
   31     }, lifetime());
   32     _wrap.setAttribute(Qt::WA_OpaquePaintEvent);
   33 
   34     auto copy = std::move(
   35         content
   36     ) | rpl::start_spawning(_wrap.lifetime());
   37 
   38     rpl::duplicate(
   39         copy
   40     ) | rpl::filter([=](const MessageBarContent &content) {
   41         return !content.title.isEmpty() || !content.text.text.isEmpty();
   42     }) | rpl::start_with_next([=](MessageBarContent &&content) {
   43         const auto creating = !_bar;
   44         if (creating) {
   45             createControls();
   46         }
   47         _bar->set(std::move(content));
   48         if (creating) {
   49             _bar->finishAnimating();
   50         }
   51     }, lifetime());
   52 
   53     std::move(
   54         copy
   55     ) | rpl::map([=](const MessageBarContent &content) {
   56         return content.title.isEmpty() || content.text.text.isEmpty();
   57     }) | rpl::start_with_next_done([=](bool hidden) {
   58         _shouldBeShown = !hidden;
   59         if (!_forceHidden) {
   60             _wrap.toggle(_shouldBeShown, anim::type::normal);
   61         } else if (!_shouldBeShown) {
   62             _bar = nullptr;
   63         }
   64     }, [=] {
   65         _forceHidden = true;
   66         _wrap.toggle(false, anim::type::normal);
   67     }, lifetime());
   68 }
   69 
   70 PinnedBar::~PinnedBar() {
   71     _rightButton.destroy();
   72 }
   73 
   74 void PinnedBar::setRightButton(object_ptr<Ui::RpWidget> button) {
   75     _rightButton.destroy();
   76     _rightButton = std::move(button);
   77     if (_rightButton) {
   78         _rightButton->setParent(_wrap.entity());
   79         _rightButton->show();
   80     }
   81     if (_bar) {
   82         updateControlsGeometry(_wrap.geometry());
   83     }
   84 }
   85 
   86 void PinnedBar::updateControlsGeometry(QRect wrapGeometry) {
   87     _bar->widget()->resizeToWidth(
   88         wrapGeometry.width() - (_rightButton ? _rightButton->width() : 0));
   89     const auto hidden = _wrap.isHidden() || !wrapGeometry.height();
   90     if (_shadow->isHidden() != hidden) {
   91         _shadow->setVisible(!hidden);
   92     }
   93     if (_rightButton) {
   94         _rightButton->moveToRight(0, 0);
   95     }
   96 }
   97 
   98 void PinnedBar::setShadowGeometryPostprocess(Fn<QRect(QRect)> postprocess) {
   99     _shadowGeometryPostprocess = std::move(postprocess);
  100     updateShadowGeometry(_wrap.geometry());
  101 }
  102 
  103 void PinnedBar::updateShadowGeometry(QRect wrapGeometry) {
  104     const auto regular = QRect(
  105         wrapGeometry.x(),
  106         wrapGeometry.y() + wrapGeometry.height(),
  107         wrapGeometry.width(),
  108         st::lineWidth);
  109     _shadow->setGeometry(_shadowGeometryPostprocess
  110         ? _shadowGeometryPostprocess(regular)
  111         : regular);
  112 }
  113 
  114 void PinnedBar::createControls() {
  115     Expects(!_bar);
  116 
  117     _bar = std::make_unique<MessageBar>(
  118         _wrap.entity(),
  119         st::defaultMessageBar);
  120     if (_rightButton) {
  121         _rightButton->raise();
  122     }
  123 
  124     // Clicks.
  125     _bar->widget()->setCursor(style::cur_pointer);
  126     _bar->widget()->events(
  127     ) | rpl::filter([=](not_null<QEvent*> event) {
  128         return (event->type() == QEvent::MouseButtonPress);
  129     }) | rpl::map([=] {
  130         return _bar->widget()->events(
  131         ) | rpl::filter([=](not_null<QEvent*> event) {
  132             return (event->type() == QEvent::MouseButtonRelease);
  133         }) | rpl::take(1) | rpl::filter([=](not_null<QEvent*> event) {
  134             return _bar->widget()->rect().contains(
  135                 static_cast<QMouseEvent*>(event.get())->pos());
  136         });
  137     }) | rpl::flatten_latest(
  138     ) | rpl::map([] {
  139         return rpl::empty_value();
  140     }) | rpl::start_to_stream(_barClicks, _bar->widget()->lifetime());
  141 
  142     _bar->widget()->move(0, 0);
  143     _bar->widget()->show();
  144     _wrap.entity()->resize(_wrap.entity()->width(), _bar->widget()->height());
  145 
  146     _wrap.geometryValue(
  147     ) | rpl::start_with_next([=](QRect rect) {
  148         updateShadowGeometry(rect);
  149         updateControlsGeometry(rect);
  150     }, _bar->widget()->lifetime());
  151 
  152     _wrap.shownValue(
  153     ) | rpl::skip(
  154         1
  155     ) | rpl::filter([=](bool shown) {
  156         return !shown && !_forceHidden;
  157     }) | rpl::start_with_next([=] {
  158         _bar = nullptr;
  159     }, _bar->widget()->lifetime());
  160 
  161     Ensures(_bar != nullptr);
  162 }
  163 
  164 void PinnedBar::show() {
  165     if (!_forceHidden) {
  166         return;
  167     }
  168     _forceHidden = false;
  169     if (_shouldBeShown) {
  170         _wrap.show(anim::type::instant);
  171         _shadow->show();
  172     }
  173 }
  174 
  175 void PinnedBar::hide() {
  176     if (_forceHidden) {
  177         return;
  178     }
  179     _forceHidden = true;
  180     _wrap.hide(anim::type::instant);
  181     _shadow->hide();
  182 }
  183 
  184 void PinnedBar::raise() {
  185     _wrap.raise();
  186     _shadow->raise();
  187 }
  188 
  189 void PinnedBar::finishAnimating() {
  190     _wrap.finishAnimating();
  191 }
  192 
  193 void PinnedBar::move(int x, int y) {
  194     _wrap.move(x, y);
  195 }
  196 
  197 void PinnedBar::resizeToWidth(int width) {
  198     _wrap.entity()->resizeToWidth(width);
  199 }
  200 
  201 int PinnedBar::height() const {
  202     return !_forceHidden
  203         ? _wrap.height()
  204         : _shouldBeShown
  205         ? st::historyReplyHeight
  206         : 0;
  207 }
  208 
  209 rpl::producer<int> PinnedBar::heightValue() const {
  210     return _wrap.heightValue();
  211 }
  212 
  213 rpl::producer<> PinnedBar::barClicks() const {
  214     return _barClicks.events();
  215 }
  216 
  217 } // namespace Ui