| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811 |
- /*
- 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 "settings/settings_scale_preview.h"
- #include "base/platform/base_platform_info.h"
- #include "base/event_filter.h"
- #include "data/data_user.h"
- #include "data/data_peer_values.h"
- #include "history/history_item_components.h"
- #include "main/main_session.h"
- #include "ui/chat/chat_style.h"
- #include "ui/chat/chat_theme.h"
- #include "ui/image/image_prepare.h"
- #include "ui/platform/ui_platform_utility.h"
- #include "ui/text/text_options.h"
- #include "ui/widgets/shadow.h"
- #include "ui/cached_round_corners.h"
- #include "ui/painter.h"
- #include "ui/ui_utility.h"
- #include "window/themes/window_theme.h"
- #include "window/section_widget.h"
- #include "window/window_controller.h"
- #include "window/window_session_controller.h"
- #include "styles/style_chat.h"
- #include <QtGui/QGuiApplication>
- #include <QtGui/QScreen>
- namespace Settings {
- namespace {
- constexpr auto kMinTextWidth = 120;
- constexpr auto kMaxTextWidth = 320;
- constexpr auto kMaxTextLines = 3;
- class Preview final {
- public:
- Preview(QWidget *slider, rpl::producer<QImage> userpic);
- void toggle(ScalePreviewShow show, int scale, int globalX);
- private:
- void init();
- void initAsWindow();
- void watchParent();
- void reparent();
- void updateToScale(int scale);
- void updateGlobalPosition(int globalX);
- void updateGlobalPosition();
- void updateWindowGlobalPosition(QPoint global);
- void updateOuterPosition(int globalX);
- [[nodiscard]] QRect adjustByScreenGeometry(QRect geometry) const;
- void toggleShown(bool shown);
- void toggleFilter();
- void update();
- void paint(Painter &p, QRect clip);
- void paintLayer(Painter &p, QRect clip);
- void paintInner(Painter &p, QRect clip);
- void paintUserpic(Painter &p, QRect clip);
- void paintBubble(Painter &p, QRect clip);
- void paintContent(Painter &p, QRect clip);
- void paintReply(Painter &p, QRect clip);
- void paintMessage(Painter &p, QRect clip);
- void validateUserpicCache();
- void validateBubbleCache();
- void validateShadowCache();
- [[nodiscard]] int scaled(int value) const;
- [[nodiscard]] QPoint scaled(QPoint value) const;
- [[nodiscard]] QMargins scaled(QMargins value) const;
- [[nodiscard]] style::font scaled(
- const style::font &value,
- int size) const;
- [[nodiscard]] style::QuoteStyle scaled(
- const style::QuoteStyle &value) const;
- [[nodiscard]] style::TextStyle scaled(
- const style::TextStyle &value,
- int fontSize) const;
- [[nodiscard]] QImage scaled(
- const style::icon &icon,
- const QColor &color) const;
- Ui::RpWidget _widget;
- not_null<QWidget*> _slider;
- Ui::ChatTheme _theme;
- style::TextStyle _nameStyle = st::fwdTextStyle;
- Ui::Text::String _nameText = { kMaxTextWidth / 3 };
- style::TextStyle _textStyle = st::messageTextStyle;
- Ui::Text::String _replyText = { kMaxTextWidth / 3 };
- Ui::Text::String _messageText = { kMaxTextWidth / 3 };
- style::Shadow _shadow = st::callShadow;
- std::array<QImage, 4> _shadowSides;
- std::array<QImage, 4> _shadowCorners;
- Ui::CornersPixmaps _bubbleCorners;
- QPixmap _bubbleShadowBottomRight;
- int _bubbleShadow = 0;
- int _localShiftLeft = 0;
- QImage _bubbleTail;
- QRect _replyRect;
- QRect _name;
- QRect _reply;
- QRect _message;
- QRect _content;
- QRect _bubble;
- QRect _userpic;
- QRect _inner;
- QRect _outer;
- QSize _minOuterSize;
- QSize _maxOuterSize;
- QImage _layer, _canvas;
- QPoint _cursor;
- std::array<QImage, 4> _canvasCornerMasks;
- QImage _userpicOriginal;
- QImage _userpicImage;
- int _scale = 0;
- int _ratio = 0;
- bool _window = false;
- Ui::Animations::Simple _shownAnimation;
- bool _shown = false;
- std::unique_ptr<QObject> _filter;
- std::unique_ptr<QObject> _parentWatcher;
- };
- Preview::Preview(QWidget *slider, rpl::producer<QImage> userpic)
- : _widget(slider->window())
- , _slider(slider)
- , _ratio(style::DevicePixelRatio())
- , _window(Ui::Platform::TranslucentWindowsSupported()) {
- std::move(userpic) | rpl::start_with_next([=](QImage &&userpic) {
- _userpicOriginal = std::move(userpic);
- if (!_userpicImage.isNull()) {
- _userpicImage = {};
- update();
- }
- }, _widget.lifetime());
- watchParent();
- init();
- }
- void Preview::watchParent() {
- const auto parent = _widget.parentWidget();
- _parentWatcher.reset(base::install_event_filter(parent, [=](
- not_null<QEvent*> e) {
- if (e->type() == QEvent::ParentChange) {
- if (_widget.window() != parent) {
- reparent();
- }
- }
- return base::EventFilterResult::Continue;
- }));
- }
- void Preview::reparent() {
- const auto parent = _widget.parentWidget();
- if (!parent) {
- // macOS just removes parenting for a _window.
- _parentWatcher = nullptr;
- return;
- }
- _widget.setParent(parent->window(), _widget.windowFlags());
- if (_shown) {
- _widget.show();
- updateGlobalPosition();
- }
- watchParent();
- }
- void Preview::toggle(ScalePreviewShow show, int scale, int sliderX) {
- if (show == ScalePreviewShow::Hide) {
- toggleShown(false);
- return;
- } else if (show == ScalePreviewShow::Update && !_shown) {
- return;
- }
- updateToScale(scale);
- updateGlobalPosition(sliderX);
- if (_widget.isHidden()) {
- Ui::ForceFullRepaintSync(&_widget);
- }
- toggleShown(true);
- }
- void Preview::toggleShown(bool shown) {
- if (_shown == shown) {
- return;
- }
- _shown = shown;
- toggleFilter();
- if (_shown) {
- _widget.show();
- } else if (_widget.isHidden()) {
- _shownAnimation.stop();
- return;
- }
- const auto callback = [=] {
- update();
- if (!_shown && !_shownAnimation.animating()) {
- _widget.hide();
- }
- };
- _shownAnimation.start(
- callback,
- shown ? 0. : 1.,
- shown ? 1. : 0.,
- st::slideWrapDuration);
- }
- void Preview::toggleFilter() {
- if (!_shown) {
- _filter = nullptr;
- return;
- } else if (_filter) {
- return;
- }
- _filter = std::make_unique<QObject>();
- const auto watch = [&](QWidget *widget, const auto &self) -> void {
- if (!widget) {
- return;
- }
- base::install_event_filter(_filter.get(), widget, [=](
- not_null<QEvent*> e) {
- if (e->type() == QEvent::Move
- || e->type() == QEvent::Resize
- || e->type() == QEvent::Show
- || e->type() == QEvent::ShowToParent
- || e->type() == QEvent::ZOrderChange) {
- updateGlobalPosition();
- }
- return base::EventFilterResult::Continue;
- });
- if (!_window && widget == _widget.window()) {
- return;
- }
- self(widget->parentWidget(), self);
- };
- watch(_slider, watch);
- const auto checkDeactivation = [=](Qt::ApplicationState state) {
- if (state != Qt::ApplicationActive) {
- toggle(ScalePreviewShow::Hide, 0, 0);
- }
- };
- QObject::connect(
- qApp,
- &QGuiApplication::applicationStateChanged,
- _filter.get(),
- checkDeactivation,
- Qt::QueuedConnection);
- }
- void Preview::update() {
- _widget.update(_outer);
- }
- void Preview::init() {
- const auto background = Window::Theme::Background();
- const auto &paper = background->paper();
- _theme.setBackground({
- .prepared = background->prepared(),
- .preparedForTiled = background->preparedForTiled(),
- .gradientForFill = background->gradientForFill(),
- .colorForFill = background->colorForFill(),
- .colors = paper.backgroundColors(),
- .patternOpacity = paper.patternOpacity(),
- .gradientRotation = paper.gradientRotation(),
- .isPattern = paper.isPattern(),
- .tile = background->tile(),
- });
- _widget.paintRequest(
- ) | rpl::start_with_next([=](QRect clip) {
- auto p = Painter(&_widget);
- paint(p, clip);
- }, _widget.lifetime());
- style::PaletteChanged(
- ) | rpl::start_with_next([=] {
- _bubbleCorners = {};
- _bubbleTail = {};
- _bubbleShadowBottomRight = {};
- update();
- }, _widget.lifetime());
- if (_window) {
- initAsWindow();
- updateToScale(style::kScaleMin);
- _minOuterSize = _outer.size();
- updateToScale(style::MaxScaleForRatio(_ratio));
- _maxOuterSize = _outer.size();
- }
- }
- int Preview::scaled(int value) const {
- return style::ConvertScale(value, _scale);
- }
- QPoint Preview::scaled(QPoint value) const {
- return { scaled(value.x()), scaled(value.y()) };
- }
- QMargins Preview::scaled(QMargins value) const {
- return {
- scaled(value.left()),
- scaled(value.top()),
- scaled(value.right()),
- scaled(value.bottom()),
- };
- }
- style::font Preview::scaled(const style::font &font, int size) const {
- return style::font(scaled(size), font->flags(), font->family());
- }
- style::QuoteStyle Preview::scaled(const style::QuoteStyle &value) const {
- return {
- .icon = value.icon,
- .scrollable = value.scrollable,
- };
- }
- style::TextStyle Preview::scaled(
- const style::TextStyle &value,
- int fontSize) const {
- return {
- .font = scaled(value.font, fontSize),
- .linkUnderline = value.linkUnderline,
- .blockquote = scaled(value.blockquote),
- .pre = scaled(value.pre),
- };
- }
- QImage Preview::scaled(
- const style::icon &icon,
- const QColor &color) const {
- return icon.instance(color, _scale);
- }
- void Preview::updateToScale(int scale) {
- using style::ConvertScale;
- if (_scale == scale) {
- return;
- }
- _scale = scale;
- _nameStyle = scaled(st::fwdTextStyle, 13);
- _textStyle = scaled(st::messageTextStyle, 13);
- _textStyle.blockquote.verticalSkip = scaled(4);
- _textStyle.blockquote.outline = scaled(3);
- _textStyle.blockquote.outlineShift = scaled(2);
- _textStyle.blockquote.radius = scaled(5);
- _textStyle.blockquote.padding = scaled(QMargins{ 10, 2, 20, 2 });
- _textStyle.blockquote.iconPosition = scaled(QPoint{ 4, 4 });
- _textStyle.pre.verticalSkip = scaled(4);
- _textStyle.pre.outline = scaled(3);
- _textStyle.pre.outlineShift = scaled(2);
- _textStyle.pre.radius = scaled(5);
- _textStyle.pre.header = scaled(20);
- _textStyle.pre.headerPosition = scaled(QPoint{ 10, 2 });
- _textStyle.pre.padding = scaled(QMargins{ 10, 2, 4, 2 });
- _textStyle.pre.iconPosition = scaled(QPoint{ 4, 2 });
- _nameText.setText(
- _nameStyle,
- u"Bob Harris"_q,
- Ui::NameTextOptions());
- _replyText.setText(
- _textStyle,
- u"Good morning!"_q,
- Ui::ItemTextDefaultOptions());
- _messageText.setText(
- _textStyle,
- u"Do you know what time it is?"_q,
- Ui::ItemTextDefaultOptions());
- const auto namePosition = QPoint(
- scaled(11), // st::historyReplyPadding.left()
- scaled(2)); // st::historyReplyPadding.top()
- const auto replyPosition = QPoint(
- scaled(11), // st::historyReplyPadding.left()
- (scaled(2) // st::historyReplyPadding.top()
- + _nameStyle.font->height)); // + st::msgServiceNameFont->height
- const auto paddingRight = scaled(6); // st::historyReplyPadding.right()
- const auto wantedWidth = std::max({
- namePosition.x() + _nameText.maxWidth() + paddingRight,
- replyPosition.x() + _replyText.maxWidth() + paddingRight,
- _messageText.maxWidth(),
- });
- const auto minTextWidth = scaled(kMinTextWidth);
- const auto maxTextWidth = scaled(kMaxTextWidth);
- const auto messageWidth = std::clamp(
- wantedWidth,
- minTextWidth,
- maxTextWidth);
- const auto messageHeight = std::min(
- _messageText.countHeight(maxTextWidth),
- kMaxTextLines * _textStyle.font->height);
- _replyRect = QRect(
- 0, // st::msgReplyBarPos.x(),
- scaled(2),// st::historyReplyTop
- messageWidth,
- (scaled(2) // st::historyReplyPadding.top()
- + _nameStyle.font->height // + st::msgServiceNameFont->height
- + _textStyle.font->height // + st::normalFont->height
- + scaled(2))); // + st::historyReplyPadding.bottom()
- _name = QRect(
- _replyRect.topLeft() + namePosition,
- QSize(messageWidth - namePosition.x(), _nameStyle.font->height));
- _reply = QRect(
- _replyRect.topLeft() + replyPosition,
- QSize(messageWidth - replyPosition.x(), _textStyle.font->height));
- _message = QRect(0, 0, messageWidth, messageHeight);
- // replyRect.bottom + st::historyReplyBottom;
- const auto replySkip = _replyRect.y() + _replyRect.height() + scaled(2);
- _message.moveTop(replySkip);
- _content = QRect(0, 0, messageWidth, replySkip + messageHeight);
- const auto msgPadding = scaled(QMargins(13, 7, 13, 8)); // st::msgPadding
- _bubble = _content.marginsAdded(msgPadding);
- _content.moveTopLeft(-_bubble.topLeft());
- _bubble.moveTopLeft({});
- _bubbleShadow = scaled(2); // st::msgShadow
- _bubbleCorners = {};
- _bubbleTail = {};
- _bubbleShadowBottomRight = {};
- const auto hasUserpic = !_userpicOriginal.isNull();
- const auto bubbleMargin = scaled(QMargins(20, 16, 20, 16));
- const auto userpicSkip = hasUserpic ? scaled(40) : 0; // st::msgPhotoSkip
- _inner = _bubble.marginsAdded(
- bubbleMargin + QMargins(userpicSkip, 0, 0, 0));
- _bubble.moveTopLeft(-_inner.topLeft());
- _inner.moveTopLeft({});
- if (hasUserpic) {
- const auto userpicSize = scaled(33); // st::msgPhotoSize
- _userpic = QRect(
- bubbleMargin.left(),
- _bubble.y() + _bubble.height() - userpicSize,
- userpicSize,
- userpicSize);
- _userpicImage = {};
- }
- _shadow.extend = scaled(QMargins(9, 8, 9, 10)); // st::callShadow.extend
- _shadowSides = {};
- _shadowCorners = {};
- update();
- _outer = _inner.marginsAdded(_shadow.extend);
- _inner.moveTopLeft(-_outer.topLeft());
- _outer.moveTopLeft({});
- _layer = QImage(
- _outer.size() * _ratio,
- QImage::Format_ARGB32_Premultiplied);
- _layer.setDevicePixelRatio(_ratio);
- _canvas = QImage(
- _inner.size() * _ratio,
- QImage::Format_ARGB32_Premultiplied);
- _canvas.setDevicePixelRatio(_ratio);
- _canvas.fill(Qt::transparent);
- _canvasCornerMasks = Images::CornersMask(scaled(6)); // st::callRadius
- }
- void Preview::updateGlobalPosition(int sliderX) {
- _localShiftLeft = sliderX;
- if (_window) {
- updateWindowGlobalPosition(_slider->mapToGlobal(QPoint()));
- } else {
- updateGlobalPosition();
- }
- }
- void Preview::updateGlobalPosition() {
- if (_window) {
- const auto global = _slider->mapToGlobal(QPoint());
- updateWindowGlobalPosition(global);
- } else {
- const auto parent = _widget.parentWidget();
- const auto global = Ui::MapFrom(parent, _slider, QPoint());
- const auto desiredLeft = global.x()
- + _localShiftLeft
- - (_outer.width() / 2);
- const auto desiredTop = global.y() - _outer.height();
- const auto requiredRight = std::min(
- desiredLeft + _outer.width(),
- parent->width());
- const auto left = std::max(
- std::min(desiredLeft, requiredRight - _outer.width()),
- 0);
- _widget.setGeometry(QRect(QPoint(left, desiredTop), _outer.size()));
- }
- _widget.raise();
- }
- void Preview::updateWindowGlobalPosition(QPoint global) {
- const auto desiredLeft = global.x() - (_minOuterSize.width() / 2);
- const auto desiredRight = global.x()
- + _slider->width()
- + (_maxOuterSize.width() / 2);
- const auto requiredLeft = desiredRight - _maxOuterSize.width();
- const auto left = std::min(desiredLeft, requiredLeft);
- const auto requiredRight = left + _maxOuterSize.width();
- const auto right = std::max(desiredRight, requiredRight);
- const auto top = global.y() - _maxOuterSize.height();
- auto result = QRect(left, top, right - left, _maxOuterSize.height());
- _widget.setGeometry(adjustByScreenGeometry(result));
- updateOuterPosition(global.x() + _localShiftLeft);
- }
- QRect Preview::adjustByScreenGeometry(QRect geometry) const {
- const auto screen = _slider->screen();
- if (!screen) {
- return geometry;
- }
- const auto screenGeometry = screen->availableGeometry();
- if (!screenGeometry.intersects(geometry)
- || screenGeometry.width() < _maxOuterSize.width()
- || screenGeometry.height() < _maxOuterSize.height()) {
- return geometry;
- }
- const auto edgeLeft = screenGeometry.x();
- const auto edgeRight = screenGeometry.x() + screenGeometry.width();
- const auto edgedRight = std::min(
- edgeRight,
- geometry.x() + geometry.width());
- const auto left = std::max(
- std::min(geometry.x(), edgedRight - _maxOuterSize.width()),
- edgeLeft);
- const auto right = std::max(edgedRight, left + _maxOuterSize.width());
- return { left, geometry.y(), right - left, geometry.height() };
- }
- void Preview::updateOuterPosition(int globalX) {
- if (_window) {
- update();
- const auto global = _widget.geometry();
- const auto desiredLeft = globalX
- - (_outer.width() / 2)
- - global.x();
- _outer.moveLeft(std::max(
- std::min(desiredLeft, global.width() - _outer.width()),
- 0));
- _outer.moveTop(_maxOuterSize.height() - _outer.height());
- update();
- }
- }
- void Preview::paint(Painter &p, QRect clip) {
- //p.setCompositionMode(QPainter::CompositionMode_Source);
- //p.fillRect(clip, Qt::transparent);
- //p.setCompositionMode(QPainter::CompositionMode_SourceOver);
- const auto outer = clip.intersected(_outer);
- if (outer.isEmpty()) {
- return;
- }
- const auto local = outer.translated(-_outer.topLeft());
- auto q = Painter(&_layer);
- q.setClipRect(local);
- paintLayer(q, local);
- q.end();
- const auto shown = _shownAnimation.value(_shown ? 1. : 0.);
- p.setClipRect(clip);
- p.setOpacity(shown);
- auto hq = std::optional<PainterHighQualityEnabler>();
- if (shown < 1.) {
- const auto middle = _outer.x() + (_outer.width() / 2);
- const auto bottom = _outer.y() + _outer.height();
- const auto scale = 0.3 + shown * 0.7;
- p.translate(middle, bottom);
- p.scale(scale, scale);
- p.translate(-middle, -bottom);
- hq.emplace(p);
- }
- p.drawImage(_outer.topLeft(), _layer);
- }
- void Preview::paintLayer(Painter &p, QRect clip) {
- p.setCompositionMode(QPainter::CompositionMode_Source);
- validateShadowCache();
- Ui::Shadow::paint(
- p,
- _inner,
- _outer.width(),
- _shadow,
- _shadowSides,
- _shadowCorners);
- const auto inner = clip.intersected(_inner);
- if (inner.isEmpty()) {
- return;
- }
- const auto local = inner.translated(-_inner.topLeft());
- auto q = Painter(&_canvas);
- q.setClipRect(local);
- paintInner(q, local);
- q.end();
- _canvas = Images::Round(std::move(_canvas), _canvasCornerMasks);
- p.setCompositionMode(QPainter::CompositionMode_SourceOver);
- p.drawImage(_inner.topLeft(), _canvas);
- }
- void Preview::paintInner(Painter &p, QRect clip) {
- Window::SectionWidget::PaintBackground(
- p,
- &_theme,
- QSize(_inner.width(), _inner.width() * 3),
- clip);
- paintUserpic(p, clip);
- p.translate(_bubble.topLeft());
- paintBubble(p, clip.translated(-_bubble.topLeft()));
- }
- void Preview::paintUserpic(Painter &p, QRect clip) {
- if (clip.intersected(_userpic).isEmpty()) {
- return;
- }
- validateUserpicCache();
- p.drawImage(_userpic.topLeft(), _userpicImage);
- }
- void Preview::paintBubble(Painter &p, QRect clip) {
- validateBubbleCache();
- const auto bubble = QRect(QPoint(), _bubble.size());
- const auto cornerShadow = _bubbleShadowBottomRight.size()
- / _bubbleShadowBottomRight.devicePixelRatio();
- p.drawPixmap(
- bubble.width() - cornerShadow.width(),
- bubble.height() + _bubbleShadow - cornerShadow.height(),
- _bubbleShadowBottomRight);
- Ui::FillRoundRect(p, bubble, st::msgInBg, _bubbleCorners);
- const auto tail = _bubbleTail.size() / _bubbleTail.devicePixelRatio();
- p.drawImage(-tail.width(), bubble.height() - tail.height(), _bubbleTail);
- p.fillRect(
- -tail.width(),
- bubble.height(),
- tail.width() + bubble.width() - cornerShadow.width(),
- _bubbleShadow,
- st::msgInShadow);
- const auto content = clip.intersected(_content);
- if (content.isEmpty()) {
- return;
- }
- p.translate(_content.topLeft());
- const auto local = content.translated(-_content.topLeft());
- p.setClipRect(local);
- paintContent(p, local);
- }
- void Preview::paintContent(Painter &p, QRect clip) {
- paintReply(p, clip);
- const auto message = clip.intersected(_message);
- if (message.isEmpty()) {
- return;
- }
- p.translate(_message.topLeft());
- const auto local = message.translated(-_message.topLeft());
- p.setClipRect(local);
- paintMessage(p, local);
- }
- void Preview::paintReply(Painter &p, QRect clip) {
- {
- auto hq = PainterHighQualityEnabler(p);
- p.setPen(Qt::NoPen);
- p.setBrush(st::msgInReplyBarColor);
- const auto outline = _textStyle.blockquote.outline;
- const auto radius = _textStyle.blockquote.radius;
- p.setOpacity(Ui::kDefaultOutline1Opacity);
- p.setClipRect(
- _replyRect.x(),
- _replyRect.y(),
- outline,
- _replyRect.height());
- p.drawRoundedRect(_replyRect, radius, radius);
- p.setOpacity(Ui::kDefaultBgOpacity);
- p.setClipRect(
- _replyRect.x() + outline,
- _replyRect.y(),
- _replyRect.width() - outline,
- _replyRect.height());
- p.drawRoundedRect(_replyRect, radius, radius);
- }
- p.setOpacity(1.);
- p.setClipping(false);
- p.setPen(st::msgInServiceFg);
- _nameText.drawLeftElided(
- p,
- _name.x(),
- _name.y(),
- _name.width(),
- _content.width());
- p.setPen(st::historyTextInFg);
- _replyText.drawLeftElided(
- p,
- _reply.x(),
- _reply.y(),
- _reply.width(),
- _content.width());
- }
- void Preview::paintMessage(Painter &p, QRect clip) {
- p.setPen(st::historyTextInFg);
- _messageText.drawLeftElided(
- p,
- 0,
- 0,
- _message.width(),
- _message.width(),
- kMaxTextLines);
- }
- void Preview::validateUserpicCache() {
- if (!_userpicImage.isNull()
- || _userpicOriginal.isNull()
- || _userpic.isEmpty()) {
- return;
- }
- _userpicImage = Images::Circle(_userpicOriginal.scaled(
- _userpic.size() * _ratio,
- Qt::IgnoreAspectRatio,
- Qt::SmoothTransformation));
- _userpicImage.setDevicePixelRatio(_ratio);
- }
- void Preview::validateBubbleCache() {
- if (!_bubbleCorners.p[0].isNull()) {
- return;
- }
- const auto radius = scaled(16); // st::bubbleRadiusLarge
- _bubbleCorners = Ui::PrepareCornerPixmaps(radius, st::msgInBg);
- _bubbleCorners.p[2] = {};
- _bubbleTail = scaled(st::historyBubbleTailInLeft, st::msgInBg->c);
- _bubbleShadowBottomRight
- = Ui::PrepareCornerPixmaps(radius, st::msgInShadow).p[3];
- }
- void Preview::validateShadowCache() {
- if (!_shadowSides[0].isNull()) {
- return;
- }
- const auto &shadowColor = st::windowShadowFg->c;
- _shadowSides[0] = scaled(st::callShadow.left, shadowColor);
- _shadowSides[1] = scaled(st::callShadow.top, shadowColor);
- _shadowSides[2] = scaled(st::callShadow.right, shadowColor);
- _shadowSides[3] = scaled(st::callShadow.bottom, shadowColor);
- _shadowCorners[0] = scaled(st::callShadow.topLeft, shadowColor);
- _shadowCorners[1] = scaled(st::callShadow.bottomLeft, shadowColor);
- _shadowCorners[2] = scaled(st::callShadow.topRight, shadowColor);
- _shadowCorners[3] = scaled(st::callShadow.bottomRight, shadowColor);
- }
- void Preview::initAsWindow() {
- _widget.setWindowFlags(Qt::WindowFlags(Qt::FramelessWindowHint)
- | Qt::BypassWindowManagerHint
- | Qt::NoDropShadowWindowHint
- | Qt::ToolTip);
- _widget.setAttribute(Qt::WA_TransparentForMouseEvents);
- _widget.hide();
- _widget.setAttribute(Qt::WA_NoSystemBackground);
- _widget.setAttribute(Qt::WA_TranslucentBackground);
- }
- } // namespace
- [[nodiscard]] Fn<void(ScalePreviewShow, int, int)> SetupScalePreview(
- not_null<Window::Controller*> window,
- not_null<Ui::RpWidget*> slider) {
- const auto controller = window->sessionController();
- const auto user = controller
- ? controller->session().user().get()
- : nullptr;
- const auto preview = slider->lifetime().make_state<Preview>(
- slider.get(),
- user ? Data::PeerUserpicImageValue(user, 160, 0) : nullptr);
- return [=](ScalePreviewShow show, int scale, int globalX) {
- preview->toggle(show, scale, globalX);
- };
- }
- } // namespace Settings
|