From c1598ff4ed8bba64d8a4aeeb594bbf37149067bd Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 17 May 2017 17:32:36 +0300 Subject: [PATCH] Highlight mentions in sticker set box title. --- Telegram/SourceFiles/boxes/abstract_box.cpp | 57 ++++++++++++------- Telegram/SourceFiles/boxes/abstract_box.h | 26 +++++++-- Telegram/SourceFiles/boxes/boxes.style | 9 +++ Telegram/SourceFiles/boxes/contacts_box.cpp | 3 +- .../SourceFiles/boxes/sticker_set_box.cpp | 16 +++++- Telegram/SourceFiles/boxes/sticker_set_box.h | 6 +- 6 files changed, 84 insertions(+), 33 deletions(-) diff --git a/Telegram/SourceFiles/boxes/abstract_box.cpp b/Telegram/SourceFiles/boxes/abstract_box.cpp index ea40f1571..a48427af0 100644 --- a/Telegram/SourceFiles/boxes/abstract_box.cpp +++ b/Telegram/SourceFiles/boxes/abstract_box.cpp @@ -26,6 +26,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "ui/effects/widget_fade_wrap.h" #include "ui/widgets/buttons.h" #include "ui/widgets/scroll_area.h" +#include "ui/widgets/labels.h" #include "mainwidget.h" #include "mainwindow.h" @@ -203,6 +204,7 @@ AbstractBox::AbstractBox(QWidget *parent, Window::Controller *controller, object void AbstractBox::setLayerType(bool layerType) { _layerType = layerType; + updateTitlePosition(); } int AbstractBox::titleHeight() const { @@ -236,23 +238,15 @@ void AbstractBox::paintEvent(QPaintEvent *e) { p.fillRect(rect, st::boxBg); } } - if (!_title.isEmpty() && clip.intersects(QRect(0, 0, width(), titleHeight()))) { - paintTitle(p, _title, _additionalTitle); + if (!_additionalTitle.isEmpty() && clip.intersects(QRect(0, 0, width(), titleHeight()))) { + paintAdditionalTitle(p); } } -void AbstractBox::paintTitle(Painter &p, const QString &title, const QString &additional) { - p.setFont(st::boxTitleFont); - p.setPen(st::boxTitleFg); - auto titleWidth = st::boxTitleFont->width(title); - auto titleLeft = _layerType ? st::boxLayerTitlePosition.x() : st::boxTitlePosition.x(); - auto titleTop = _layerType ? st::boxLayerTitlePosition.y() : st::boxTitlePosition.y(); - p.drawTextLeft(titleLeft, titleTop, width(), title, titleWidth); - if (!additional.isEmpty()) { - p.setFont(st::boxLayerTitleAdditionalFont); - p.setPen(st::boxTitleAdditionalFg); - p.drawTextLeft(titleLeft + titleWidth + st::boxLayerTitleAdditionalSkip, titleTop + st::boxTitleFont->ascent - st::boxLayerTitleAdditionalFont->ascent, width(), additional); - } +void AbstractBox::paintAdditionalTitle(Painter &p) { + p.setFont(st::boxLayerTitleAdditionalFont); + p.setPen(st::boxTitleAdditionalFg); + p.drawTextLeft(_titleLeft + (_title ? _title->width() : 0) + st::boxLayerTitleAdditionalSkip, _titleTop + st::boxTitleFont->ascent - st::boxLayerTitleAdditionalFont->ascent, width(), _additionalTitle); } void AbstractBox::parentResized() { @@ -262,18 +256,33 @@ void AbstractBox::parentResized() { update(); } -void AbstractBox::setTitle(const QString &title, const QString &additional) { +void AbstractBox::setTitle(const QString &title) { + setTitle({ title, EntitiesInText() }); +} + +void AbstractBox::setTitle(const TextWithEntities &title) { auto wasTitle = hasTitle(); - _title = title; - _additionalTitle = additional; - update(); + if (!title.text.isEmpty()) { + if (!_title) { + _title.create(this, st::boxTitle); + } + _title->setMarkedText(title); + updateTitlePosition(); + } else { + _title.destroy(); + } if (wasTitle != hasTitle()) { updateSize(); } } +void AbstractBox::setAdditionalTitle(const QString &additional) { + _additionalTitle = additional; + update(); +} + bool AbstractBox::hasTitle() const { - return !_title.isEmpty() || !_additionalTitle.isEmpty(); + return (_title != nullptr) || !_additionalTitle.isEmpty(); } void AbstractBox::updateSize() { @@ -295,6 +304,15 @@ void AbstractBox::updateButtonsPositions() { } } +void AbstractBox::updateTitlePosition() { + _titleLeft = _layerType ? st::boxLayerTitlePosition.x() : st::boxTitlePosition.x(); + _titleTop = _layerType ? st::boxLayerTitlePosition.y() : st::boxTitlePosition.y(); + if (_title) { + _title->resizeToWidth(qMin(_title->naturalWidth(), width() - _titleLeft * 2)); + _title->moveToLeft(_titleLeft, _titleTop); + } +} + void AbstractBox::clearButtons() { for (auto &button : base::take(_buttons)) { button.destroy(); @@ -358,6 +376,7 @@ int AbstractBox::contentTop() const { void AbstractBox::resizeEvent(QResizeEvent *e) { updateButtonsPositions(); + updateTitlePosition(); auto top = contentTop(); _content->resize(width(), height() - top - buttonsHeight()); diff --git a/Telegram/SourceFiles/boxes/abstract_box.h b/Telegram/SourceFiles/boxes/abstract_box.h index 234a50857..386d44c8e 100644 --- a/Telegram/SourceFiles/boxes/abstract_box.h +++ b/Telegram/SourceFiles/boxes/abstract_box.h @@ -27,6 +27,7 @@ namespace Ui { class RoundButton; class IconButton; class ScrollArea; +class FlatLabel; template class WidgetFadeWrap; } // namespace Ui @@ -46,7 +47,9 @@ public: virtual Window::Controller *controller() const = 0; virtual void setLayerType(bool layerType) = 0; - virtual void setTitle(const QString &title, const QString &additional) = 0; + virtual void setTitle(const QString &title) = 0; + virtual void setTitle(const TextWithEntities &title) = 0; + virtual void setAdditionalTitle(const QString &additional) = 0; virtual void clearButtons() = 0; virtual QPointer addButton(const QString &text, base::lambda clickCallback, const style::RoundButton &st) = 0; @@ -75,8 +78,14 @@ public: getDelegate()->closeBox(); } - void setTitle(const QString &title, const QString &additional = QString()) { - getDelegate()->setTitle(title, additional); + void setTitle(const QString &title) { + getDelegate()->setTitle(title); + } + void setTitle(const TextWithEntities &title) { + getDelegate()->setTitle(title); + } + void setAdditionalTitle(const QString &additional) { + getDelegate()->setAdditionalTitle(additional); } void clearButtons() { @@ -199,7 +208,9 @@ public: void parentResized() override; void setLayerType(bool layerType) override; - void setTitle(const QString &title, const QString &additional) override; + void setTitle(const QString &title) override; + void setTitle(const TextWithEntities &title) override; + void setAdditionalTitle(const QString &additional) override; void clearButtons() override; QPointer addButton(const QString &text, base::lambda clickCallback, const style::RoundButton &st) override; @@ -235,7 +246,8 @@ protected: } private: - void paintTitle(Painter &p, const QString &title, const QString &additional = QString()); + void paintAdditionalTitle(Painter &p); + void updateTitlePosition(); bool hasTitle() const; int titleHeight() const; @@ -253,8 +265,10 @@ private: int _maxContentHeight = 0; object_ptr _content; - QString _title; + object_ptr _title = { nullptr }; QString _additionalTitle; + int _titleLeft = 0; + int _titleTop = 0; bool _layerType = false; std::vector> _buttons; diff --git a/Telegram/SourceFiles/boxes/boxes.style b/Telegram/SourceFiles/boxes/boxes.style index 34f9811a0..bfb390702 100644 --- a/Telegram/SourceFiles/boxes/boxes.style +++ b/Telegram/SourceFiles/boxes/boxes.style @@ -73,6 +73,15 @@ boxRoundShadow: Shadow { } boxTitleFont: font(17px semibold); +boxTitle: FlatLabel(defaultFlatLabel) { + textFg: boxTitleFg; + maxHeight: 24px; + style: TextStyle(defaultTextStyle) { + font: boxTitleFont; + linkFont: boxTitleFont; + linkFontOver: font(17px semibold underline); + } +} boxTitlePosition: point(23px, 20px); boxTitleHeight: 56px; boxLayerTitlePosition: point(23px, 16px); diff --git a/Telegram/SourceFiles/boxes/contacts_box.cpp b/Telegram/SourceFiles/boxes/contacts_box.cpp index e1a17dff8..0364fb6a0 100644 --- a/Telegram/SourceFiles/boxes/contacts_box.cpp +++ b/Telegram/SourceFiles/boxes/contacts_box.cpp @@ -204,7 +204,8 @@ void ContactsBox::updateTitle() { auto addingAdmin = _channel && (_membersFilter == MembersFilter::Admins); auto title = lang(addingAdmin ? lng_channel_add_admin : lng_profile_add_participant); auto additional = (addingAdmin || (_inner->channel() && !_inner->channel()->isMegagroup())) ? QString() : QString("%1 / %2").arg(_inner->selectedCount()).arg(Global::MegagroupSizeMax()); - setTitle(title, additional); + setTitle(title); + setAdditionalTitle(additional); } else if (_inner->sharingBotGame()) { setTitle(lang(lng_bot_choose_chat)); } else if (_inner->bot()) { diff --git a/Telegram/SourceFiles/boxes/sticker_set_box.cpp b/Telegram/SourceFiles/boxes/sticker_set_box.cpp index 07b0c458a..d97d04325 100644 --- a/Telegram/SourceFiles/boxes/sticker_set_box.cpp +++ b/Telegram/SourceFiles/boxes/sticker_set_box.cpp @@ -165,7 +165,6 @@ void StickerSetBox::Inner::gotSet(const MTPmessages_StickerSet &set) { if (d.vset.type() == mtpc_stickerSet) { auto &s = d.vset.c_stickerSet(); _setTitle = stickerSetTitle(s); - _title = st::boxTitleFont->elided(_setTitle, width() - st::boxTitlePosition.x() - st::boxTitleHeight); _setShortName = qs(s.vshort_name); _setId = s.vid.v; _setAccess = s.vaccess_hash.v; @@ -428,8 +427,19 @@ bool StickerSetBox::Inner::official() const { return _loaded && _setShortName.isEmpty(); } -QString StickerSetBox::Inner::title() const { - return _loaded ? (_pack.isEmpty() ? lang(lng_attach_failed) : _title) : lang(lng_contacts_loading); +TextWithEntities StickerSetBox::Inner::title() const { + auto text = _setTitle; + auto entities = EntitiesInText(); + if (_loaded) { + if (_pack.isEmpty()) { + text = lang(lng_attach_failed); + } else { + textParseEntities(text, TextParseMentions, &entities); + } + } else { + text = lang(lng_contacts_loading); + } + return { text, entities }; } QString StickerSetBox::Inner::shortName() const { diff --git a/Telegram/SourceFiles/boxes/sticker_set_box.h b/Telegram/SourceFiles/boxes/sticker_set_box.h index 58f70a7d0..77a982a87 100644 --- a/Telegram/SourceFiles/boxes/sticker_set_box.h +++ b/Telegram/SourceFiles/boxes/sticker_set_box.h @@ -59,8 +59,6 @@ private: class Inner; QPointer _inner; - QString _title; - }; // This class is hold in header because it requires Qt preprocessing. @@ -73,7 +71,7 @@ public: bool loaded() const; int32 notInstalled() const; bool official() const; - QString title() const; + TextWithEntities title() const; QString shortName() const; void setVisibleTopBottom(int visibleTop, int visibleBottom) override; @@ -117,7 +115,7 @@ private: bool _loaded = false; uint64 _setId = 0; uint64 _setAccess = 0; - QString _title, _setTitle, _setShortName; + QString _setTitle, _setShortName; int32 _setCount = 0; int32 _setHash = 0; MTPDstickerSet::Flags _setFlags = 0;