diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index 0f7acc35a..65cf0717e 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -42,11 +42,10 @@ ApiWrap::ApiWrap(QObject *parent) : QObject(parent) void ApiWrap::init() { } -void ApiWrap::requestMessageData(ChannelData *channel, MsgId msgId, std_::unique_ptr callback) { +void ApiWrap::requestMessageData(ChannelData *channel, MsgId msgId, RequestMessageDataCallback &&callback) { MessageDataRequest &req(channel ? _channelMessageDataRequests[channel][msgId] : _messageDataRequests[msgId]); if (callback) { - MessageDataRequest::CallbackPtr pcallback(callback.release()); - req.callbacks.append(pcallback); + req.callbacks.append(std_::move(callback)); } if (!req.req) _messageDataResolveDelayed->call(); } @@ -138,7 +137,7 @@ void ApiWrap::gotMessageDatas(ChannelData *channel, const MTPmessages_Messages & for (auto i = requests->begin(); i != requests->cend();) { if (i.value().req == req) { for_const (auto &callback, i.value().callbacks) { - callback->call(channel, i.key()); + callback(channel, i.key()); } i = requests->erase(i); } else { diff --git a/Telegram/SourceFiles/apiwrap.h b/Telegram/SourceFiles/apiwrap.h index e4c83a8d6..524f195c6 100644 --- a/Telegram/SourceFiles/apiwrap.h +++ b/Telegram/SourceFiles/apiwrap.h @@ -28,8 +28,8 @@ public: ApiWrap(QObject *parent); void init(); - using RequestMessageDataCallback = SharedCallback; - void requestMessageData(ChannelData *channel, MsgId msgId, std_::unique_ptr callback); + using RequestMessageDataCallback = base::lambda_wrap; + void requestMessageData(ChannelData *channel, MsgId msgId, RequestMessageDataCallback &&callback); void requestFullPeer(PeerData *peer); void requestPeer(PeerData *peer); @@ -82,11 +82,8 @@ private: void gotMessageDatas(ChannelData *channel, const MTPmessages_Messages &result, mtpRequestId req); struct MessageDataRequest { - MessageDataRequest() : req(0) { - } - typedef SharedCallback::Ptr CallbackPtr; - typedef QList Callbacks; - mtpRequestId req; + using Callbacks = QList; + mtpRequestId req = 0; Callbacks callbacks; }; typedef QMap MessageDataRequests; diff --git a/Telegram/SourceFiles/boxes/sharebox.cpp b/Telegram/SourceFiles/boxes/sharebox.cpp index 37084e249..19b249b36 100644 --- a/Telegram/SourceFiles/boxes/sharebox.cpp +++ b/Telegram/SourceFiles/boxes/sharebox.cpp @@ -227,9 +227,9 @@ void ShareBox::onMustScrollTo(int top, int bottom) { to = bottom - (scrollBottom - scrollTop); } if (from != to) { - START_ANIMATION(_scrollAnimation, func([this]() { + _scrollAnimation.start([this]() { scrollArea()->scrollToY(_scrollAnimation.current(scrollArea()->scrollTop())); - }), from, to, st::shareScrollDuration, anim::sineInOut); + }, from, to, st::shareScrollDuration, anim::sineInOut); } } @@ -437,9 +437,9 @@ void ShareInner::setActive(int active) { if (active != _active) { auto changeNameFg = [this](int index, style::color from, style::color to) { if (auto chat = getChatAtIndex(index)) { - START_ANIMATION(chat->nameFg, func([this, chat] { + chat->nameFg.start([this, chat] { repaintChat(chat->peer); - }), from->c, to->c, st::shareActivateDuration, anim::linear); + }, from->c, to->c, st::shareActivateDuration); } }; changeNameFg(_active, st::shareNameActiveFg, st::shareNameFg); @@ -459,16 +459,7 @@ void ShareInner::paintChat(Painter &p, Chat *chat, int index) { auto w = width(); auto photoLeft = (_rowWidth - (st::sharePhotoRadius * 2)) / 2; auto photoTop = st::sharePhotoTop; - if (chat->selection.isNull()) { - if (!chat->wideUserpicCache.isNull()) { - chat->wideUserpicCache = QPixmap(); - } - auto userpicRadius = chat->selected ? st::sharePhotoSmallRadius : st::sharePhotoRadius; - auto userpicShift = st::sharePhotoRadius - userpicRadius; - auto userpicLeft = x + photoLeft + userpicShift; - auto userpicTop = y + photoTop + userpicShift; - chat->peer->paintUserpicLeft(p, userpicRadius * 2, userpicLeft, userpicTop, w); - } else { + if (chat->selection.animating()) { p.setRenderHint(QPainter::SmoothPixmapTransform, true); auto userpicRadius = qRound(WideCacheScale * (st::sharePhotoRadius + (st::sharePhotoSmallRadius - st::sharePhotoRadius) * selectionLevel)); auto userpicShift = WideCacheScale * st::sharePhotoRadius - userpicRadius; @@ -478,6 +469,15 @@ void ShareInner::paintChat(Painter &p, Chat *chat, int index) { auto from = QRect(QPoint(0, 0), chat->wideUserpicCache.size()); p.drawPixmapLeft(to, w, chat->wideUserpicCache, from); p.setRenderHint(QPainter::SmoothPixmapTransform, false); + } else { + if (!chat->wideUserpicCache.isNull()) { + chat->wideUserpicCache = QPixmap(); + } + auto userpicRadius = chat->selected ? st::sharePhotoSmallRadius : st::sharePhotoRadius; + auto userpicShift = st::sharePhotoRadius - userpicRadius; + auto userpicLeft = x + photoLeft + userpicShift; + auto userpicTop = y + photoTop + userpicShift; + chat->peer->paintUserpicLeft(p, userpicRadius * 2, userpicLeft, userpicTop, w); } if (selectionLevel > 0) { @@ -516,11 +516,12 @@ void ShareInner::paintChat(Painter &p, Chat *chat, int index) { p.setRenderHint(QPainter::SmoothPixmapTransform, false); p.setOpacity(1.); - if (chat->nameFg.isNull()) { - p.setPen((index == _active) ? st::shareNameActiveFg : st::shareNameFg); - } else { + if (chat->nameFg.animating()) { p.setPen(chat->nameFg.current()); + } else { + p.setPen((index == _active) ? st::shareNameActiveFg : st::shareNameFg); } + auto nameWidth = (_rowWidth - st::shareColumnSkip); auto nameLeft = st::shareColumnSkip / 2; auto nameTop = photoTop + st::sharePhotoRadius * 2 + st::shareNameTop; @@ -670,21 +671,21 @@ void ShareInner::changeCheckState(Chat *chat) { if (chat->selected) { _selected.insert(chat->peer); chat->icons.push_back(Chat::Icon()); - START_ANIMATION(chat->icons.back().fadeIn, func([this, chat] { + chat->icons.back().fadeIn.start([this, chat] { repaintChat(chat->peer); - }), 0, 1, st::shareSelectDuration, anim::linear); + }, 0, 1, st::shareSelectDuration); } else { _selected.remove(chat->peer); prepareWideCheckIconCache(&chat->icons.back()); - START_ANIMATION(chat->icons.back().fadeOut, func([this, chat] { - removeFadeOutedIcons(chat); + chat->icons.back().fadeOut.start([this, chat] { repaintChat(chat->peer); - }), 1, 0, st::shareSelectDuration, anim::linear); + removeFadeOutedIcons(chat); // this call can destroy current lambda + }, 1, 0, st::shareSelectDuration); } prepareWideUserpicCache(chat); - START_ANIMATION(chat->selection, func([this, chat] { + chat->selection.start([this, chat] { repaintChat(chat->peer); - }), chat->selected ? 0 : 1, chat->selected ? 1 : 0, st::shareSelectDuration, anim_bumpy); + }, chat->selected ? 0 : 1, chat->selected ? 1 : 0, st::shareSelectDuration, anim_bumpy); if (chat->selected) { setActive(chatIndex(chat->peer)); } @@ -692,9 +693,9 @@ void ShareInner::changeCheckState(Chat *chat) { } void ShareInner::removeFadeOutedIcons(Chat *chat) { - while (!chat->icons.empty() && chat->icons.front().fadeIn.isNull() && chat->icons.front().fadeOut.isNull()) { + while (!chat->icons.empty() && !chat->icons.front().fadeIn.animating() && !chat->icons.front().fadeOut.animating()) { if (chat->icons.size() > 1 || !chat->selected) { - chat->icons.pop_front(); + chat->icons.erase(chat->icons.begin()); } else { break; } @@ -1016,18 +1017,6 @@ void shareGameScoreFromItem(HistoryItem *item) { Ui::showLayer(new ShareBox(std_::move(copyCallback), std_::move(submitCallback))); } -class GameMessageResolvedCallback : public SharedCallback { -public: - void call(ChannelData *channel, MsgId msgId) const override { - if (auto item = App::histItemById(channel, msgId)) { - shareGameScoreFromItem(item); - } else { - Ui::showLayer(new InformBox(lang(lng_edit_deleted))); - } - } - -}; - } // namespace void shareGameScoreByHash(const QString &hash) { @@ -1062,7 +1051,13 @@ void shareGameScoreByHash(const QString &hash) { } else if (App::api()) { auto channel = channelId ? App::channelLoaded(channelId) : nullptr; if (channel || !channelId) { - App::api()->requestMessageData(channel, msgId, std_::make_unique()); + App::api()->requestMessageData(channel, msgId, [](ChannelData *channel, MsgId msgId) { + if (auto item = App::histItemById(channel, msgId)) { + shareGameScoreFromItem(item); + } else { + Ui::showLayer(new InformBox(lang(lng_edit_deleted))); + } + }); } } } diff --git a/Telegram/SourceFiles/boxes/sharebox.h b/Telegram/SourceFiles/boxes/sharebox.h index 696a28242..675fb92aa 100644 --- a/Telegram/SourceFiles/boxes/sharebox.h +++ b/Telegram/SourceFiles/boxes/sharebox.h @@ -23,6 +23,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "abstractbox.h" #include "core/lambda_wrap.h" #include "core/observer.h" +#include "core/vector_of_moveable.h" namespace Dialogs { class Row; @@ -163,7 +164,7 @@ private: FloatAnimation fadeOut; QPixmap wideCheckCache; }; - QList icons; + std_::vector_of_moveable icons; }; void paintChat(Painter &p, Chat *chat, int index); void updateChat(PeerData *peer); diff --git a/Telegram/SourceFiles/boxes/stickersetbox.cpp b/Telegram/SourceFiles/boxes/stickersetbox.cpp index 0f9974954..728cee690 100644 --- a/Telegram/SourceFiles/boxes/stickersetbox.cpp +++ b/Telegram/SourceFiles/boxes/stickersetbox.cpp @@ -62,8 +62,8 @@ void StickerSetInner::gotSet(const MTPmessages_StickerSet &set) { _selected = -1; setCursor(style::cur_default); if (set.type() == mtpc_messages_stickerSet) { - auto &d(set.c_messages_stickerSet()); - auto &v(d.vdocuments.c_vector().v); + auto &d = set.c_messages_stickerSet(); + auto &v = d.vdocuments.c_vector().v; _pack.reserve(v.size()); _packOvers.reserve(v.size()); for (int i = 0, l = v.size(); i < l; ++i) { @@ -247,13 +247,13 @@ void StickerSetInner::updateSelected() { void StickerSetInner::startOverAnimation(int index, float64 from, float64 to) { if (index >= 0 && index < _packOvers.size()) { - START_ANIMATION(_packOvers[index], func([this, index]() { + _packOvers[index].start([this, index] { int row = index / StickerPanPerRow; int column = index % StickerPanPerRow; int left = st::stickersPadding.left() + column * st::stickersSize.width(); int top = st::stickersPadding.top() + row * st::stickersSize.height(); rtlupdate(left, top, st::stickersSize.width(), st::stickersSize.height()); - }), from, to, st::emojiPanDuration, anim::linear); + }, from, to, st::emojiPanDuration); } } diff --git a/Telegram/SourceFiles/boxes/stickersetbox.h b/Telegram/SourceFiles/boxes/stickersetbox.h index 699780a97..3c7a936a3 100644 --- a/Telegram/SourceFiles/boxes/stickersetbox.h +++ b/Telegram/SourceFiles/boxes/stickersetbox.h @@ -21,6 +21,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #pragma once #include "abstractbox.h" +#include "core/vector_of_moveable.h" class ConfirmBox; @@ -69,7 +70,7 @@ private: return (_setFlags & MTPDstickerSet::Flag::f_masks); } - QVector _packOvers; + std_::vector_of_moveable _packOvers; StickerPack _pack; StickersByEmojiMap _emoji; bool _loaded = false; diff --git a/Telegram/SourceFiles/core/basic_types.h b/Telegram/SourceFiles/core/basic_types.h index 68dd42b2e..778aff01b 100644 --- a/Telegram/SourceFiles/core/basic_types.h +++ b/Telegram/SourceFiles/core/basic_types.h @@ -20,6 +20,17 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org */ #pragma once +#include +#include + +#include + +#include + +#ifndef OS_MAC_OLD +#include +#endif // OS_MAC_OLD + template void deleteAndMark(T *&link) { delete link; @@ -259,13 +270,6 @@ typedef float float32; typedef double float64; #endif -#include -#include - -#include - -#include - using std::string; using std::exception; #ifdef OS_MAC_OLD @@ -1035,13 +1039,15 @@ struct ComponentWrapStruct { // global scope, so it will be filled by zeros from the start ComponentWrapStruct() { } - ComponentWrapStruct(int size, ComponentConstruct construct, ComponentDestruct destruct, ComponentMove move) + ComponentWrapStruct(std::size_t size, std::size_t align, ComponentConstruct construct, ComponentDestruct destruct, ComponentMove move) : Size(size) + , Align(align) , Construct(construct) , Destruct(destruct) , Move(move) { } - int Size; + std::size_t Size; + std::size_t Align; ComponentConstruct Construct; ComponentDestruct Destruct; ComponentMove Move; @@ -1058,6 +1064,7 @@ extern QAtomicInt ComponentIndexLast; template struct BaseComponent { BaseComponent() { + static_assert(alignof(Type) <= sizeof(SmallestSizeType), "Components should align to a pointer!"); } BaseComponent(const BaseComponent &other) = delete; BaseComponent &operator=(const BaseComponent &other) = delete; @@ -1075,8 +1082,11 @@ struct BaseComponent { t_assert(last < 64); if (_index.testAndSetOrdered(0, last + 1)) { ComponentWraps[last] = ComponentWrapStruct( - CeilDivideMinimumOne::Result * sizeof(uint64), - Type::ComponentConstruct, Type::ComponentDestruct, Type::ComponentMove); + CeilDivideMinimumOne::Result * sizeof(SmallestSizeType), + alignof(Type), + Type::ComponentConstruct, + Type::ComponentDestruct, + Type::ComponentMove); } break; } @@ -1088,6 +1098,8 @@ struct BaseComponent { } protected: + using SmallestSizeType = void*; + static void ComponentConstruct(void *location, Composer *composer) { new (location) Type(); } @@ -1102,7 +1114,6 @@ protected: class ComposerMetadata { public: - ComposerMetadata(uint64 mask) : size(0), last(64), _mask(mask) { for (int i = 0; i < 64; ++i) { uint64 m = (1ULL << i); @@ -1147,15 +1158,13 @@ const ComposerMetadata *GetComposerMetadata(uint64 mask); class Composer { public: - Composer(uint64 mask = 0) : _data(zerodata()) { if (mask) { const ComposerMetadata *meta = GetComposerMetadata(mask); int size = sizeof(meta) + meta->size; - void *data = operator new(size); - if (!data) { // terminate if we can't allocate memory - throw "Can't allocate memory!"; - } + + auto data = operator new(size); + t_assert(data != nullptr); _data = data; _meta() = meta; @@ -1163,7 +1172,13 @@ public: int offset = meta->offsets[i]; if (offset >= 0) { try { - ComponentWraps[i].Construct(_dataptrunsafe(offset), this); + auto constructAt = _dataptrunsafe(offset); +#ifndef OS_MAC_OLD + auto space = ComponentWraps[i].Size; + auto alignedAt = std::align(ComponentWraps[i].Align, space, constructAt, space); + t_assert(alignedAt == constructAt); +#endif // OS_MAC_OLD + ComponentWraps[i].Construct(constructAt, this); } catch (...) { while (i > 0) { --i; @@ -1182,7 +1197,7 @@ public: Composer &operator=(const Composer &other) = delete; ~Composer() { if (_data != zerodata()) { - const ComposerMetadata *meta = _meta(); + auto meta = _meta(); for (int i = 0; i < meta->last; ++i) { int offset = meta->offsets[i]; if (offset >= 0) { @@ -1213,7 +1228,7 @@ protected: Composer tmp(mask); tmp.swap(*this); if (_data != zerodata() && tmp._data != zerodata()) { - const ComposerMetadata *meta = _meta(), *wasmeta = tmp._meta(); + auto meta = _meta(), wasmeta = tmp._meta(); for (int i = 0; i < meta->last; ++i) { int offset = meta->offsets[i], wasoffset = wasmeta->offsets[i]; if (offset >= 0 && wasoffset >= 0) { @@ -1252,103 +1267,3 @@ private: } }; - -template -class SharedCallback { -public: - virtual R call(Args... args) const = 0; - virtual ~SharedCallback() { - } - using Ptr = QSharedPointer>; - -}; - -template -class FunctionImplementation { -public: - virtual R call(Args... args) = 0; - virtual void destroy() { delete this; } - virtual ~FunctionImplementation() {} - -}; - -template -class NullFunctionImplementation : public FunctionImplementation { -public: - R call(Args... args) override { return R(); } - void destroy() override {} - static NullFunctionImplementation SharedInstance; - -}; -template -NullFunctionImplementation NullFunctionImplementation::SharedInstance; - -template -class Function { -public: - Function() : _implementation(nullImpl()) {} - Function(FunctionImplementation *implementation) : _implementation(implementation) {} - Function(const Function &other) = delete; - Function &operator=(const Function &other) = delete; - Function(Function &&other) : _implementation(other._implementation) { - other._implementation = nullImpl(); - } - Function &operator=(Function &&other) { - std::swap(_implementation, other._implementation); - return *this; - } - - bool isNull() const { - return (_implementation == nullImpl()); - } - - R call(Args... args) { return _implementation->call(args...); } - ~Function() { - if (_implementation) { - _implementation->destroy(); - _implementation = nullptr; - } - deleteAndMark(_implementation); - } - -private: - static FunctionImplementation *nullImpl() { - return &NullFunctionImplementation::SharedInstance; - } - - FunctionImplementation *_implementation; - -}; - -template -class WrappedFunction : public FunctionImplementation { -public: - using Method = R(*)(Args... args); - WrappedFunction(Method method) : _method(method) {} - R call(Args... args) override { return (*_method)(args...); } - -private: - Method _method; - -}; -template -inline Function func(R(*method)(Args... args)) { - return Function(new WrappedFunction(method)); -} - -template -class ObjectFunction : public FunctionImplementation { -public: - using Method = R(I::*)(Args... args); - ObjectFunction(O *obj, Method method) : _obj(obj), _method(method) {} - R call(Args... args) override { return (_obj->*_method)(args...); } - -private: - O *_obj; - Method _method; - -}; -template -inline Function func(O *obj, R(I::*method)(Args...)) { - return Function(new ObjectFunction(obj, method)); -} diff --git a/Telegram/SourceFiles/core/lambda_wrap.h b/Telegram/SourceFiles/core/lambda_wrap.h index 77982086c..9bc1fe084 100644 --- a/Telegram/SourceFiles/core/lambda_wrap.h +++ b/Telegram/SourceFiles/core/lambda_wrap.h @@ -373,48 +373,20 @@ public: } // namespace base -// While we still use Function<> +// While we still use rpcDone() and rpcFail() + +#include "mtproto/rpc_sender.h" template -struct LambdaFunctionHelper; +struct LambdaUniqueHelper; template -struct LambdaFunctionHelper { - using FunctionType = Function; +struct LambdaUniqueHelper { using UniqueType = base::lambda_unique; }; template -using LambdaGetFunction = typename LambdaFunctionHelper::FunctionType; - -template -using LambdaGetUnique = typename LambdaFunctionHelper::UniqueType; - -template -class LambdaFunctionImplementation : public FunctionImplementation { -public: - LambdaFunctionImplementation(base::lambda_unique &&lambda) : _lambda(std_::move(lambda)) { - } - R call(Args... args) override { return _lambda(std_::forward(args)...); } - -private: - base::lambda_unique _lambda; - -}; - -template -inline Function func_lambda_wrap_helper(base::lambda_unique &&lambda) { - return Function(new LambdaFunctionImplementation(std_::move(lambda))); -} - -template ::value>> -inline LambdaGetFunction func(Lambda &&lambda) { - return func_lambda_wrap_helper(LambdaGetUnique(std_::move(lambda))); -} - -// While we still use rpcDone() and rpcFail() - -#include "mtproto/rpc_sender.h" +using LambdaGetUnique = typename LambdaUniqueHelper::UniqueType; template class RPCHandlerImplementation : public Base { diff --git a/Telegram/SourceFiles/core/observer.h b/Telegram/SourceFiles/core/observer.h index f37494625..97665a294 100644 --- a/Telegram/SourceFiles/core/observer.h +++ b/Telegram/SourceFiles/core/observer.h @@ -58,7 +58,7 @@ private: }; -// Handler is one of Function<> instantiations. +// Handler is one of base::lambda_unique<> instantiations. template struct ObserversList { struct Entry { @@ -109,8 +109,8 @@ public: // entries list while the loop is still running. for (int i = 0; i < entries.size(); ++i) { auto &entry = entries[i]; - if (!entry.handler.isNull() && (flags & entry.flags)) { - entry.handler.call(std_::forward(args)...); + if (entry.handler && (flags & entry.flags)) { + entry.handler(std_::forward(args)...); } } } @@ -140,7 +140,7 @@ private: if (entries.size() <= connectionIndex) return; if (entries.size() == connectionIndex + 1) { - for (entries.pop_back(); !entries.isEmpty() && entries.back().handler.isNull();) { + for (entries.pop_back(); !entries.isEmpty() && !entries.back().handler;) { entries.pop_back(); } } else { diff --git a/Telegram/SourceFiles/core/vector_of_moveable.h b/Telegram/SourceFiles/core/vector_of_moveable.h index 861b184ec..7077237d4 100644 --- a/Telegram/SourceFiles/core/vector_of_moveable.h +++ b/Telegram/SourceFiles/core/vector_of_moveable.h @@ -93,6 +93,7 @@ public: *prev = std_::move(*next); } --_size; + end()->~T(); return it; } @@ -143,15 +144,21 @@ public: } inline const T &at(int index) const { if (index < 0 || index >= _size) { -#if QT_VERSION < QT_VERSION_CHECK(5, 5, 0) - throw std::exception(); -#else // QT_VERSION < 5.5.0 +#ifndef OS_MAC_OLD throw std::out_of_range(""); -#endif // QT_VERSION < 5.5.0 +#else // OS_MAC_OLD + throw std::exception(); +#endif // OS_MAC_OLD } return data()[index]; } + void reserve(int newCapacity) { + if (newCapacity > _capacity) { + reallocate(newCapacity); + } + } + inline ~vector_of_moveable() { clear(); } diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp index be131950d..59281428e 100644 --- a/Telegram/SourceFiles/history.cpp +++ b/Telegram/SourceFiles/history.cpp @@ -2644,10 +2644,12 @@ void HistoryMessageReplyMarkup::create(const MTPReplyMarkup &markup) { } } -void HistoryDependentItemCallback::call(ChannelData *channel, MsgId msgId) const { - if (HistoryItem *item = App::histItemById(_dependent)) { - item->updateDependencyItem(); - } +ApiWrap::RequestMessageDataCallback historyDependentItemCallback(const FullMsgId &msgId) { + return [dependent = msgId](ChannelData *channel, MsgId msgId) { + if (HistoryItem *item = App::histItemById(dependent)) { + item->updateDependencyItem(); + } + }; } void HistoryMessageUnreadBar::init(int count) { @@ -4910,7 +4912,9 @@ bool HistoryGif::playInline(bool autoplay) { if (!cAutoPlayGif()) { App::stopGifItems(); } - _gif = new Media::Clip::Reader(_data->location(), _data->data(), func(_parent, &HistoryItem::clipCallback)); + _gif = new Media::Clip::Reader(_data->location(), _data->data(), [this](Media::Clip::Notification notification) { + _parent->clipCallback(notification); + }); App::regGifItem(_gif, _parent); if (gif()) _gif->setAutoplay(); } @@ -6837,7 +6841,7 @@ void HistoryMessage::createComponents(const CreateConfig &config) { if (auto reply = Get()) { reply->replyToMsgId = config.replyTo; if (!reply->updateData(this) && App::api()) { - App::api()->requestMessageData(history()->peer->asChannel(), reply->replyToMsgId, std_::make_unique(fullId())); + App::api()->requestMessageData(history()->peer->asChannel(), reply->replyToMsgId, historyDependentItemCallback(fullId())); } } if (auto via = Get()) { @@ -8388,7 +8392,7 @@ void HistoryService::createFromMtp(const MTPDmessageService &message) { if (auto dependent = GetDependentData()) { dependent->msgId = message.vreply_to_msg_id.v; if (!updateDependent() && App::api()) { - App::api()->requestMessageData(history()->peer->asChannel(), dependent->msgId, std_::make_unique(fullId())); + App::api()->requestMessageData(history()->peer->asChannel(), dependent->msgId, historyDependentItemCallback(fullId())); } } } diff --git a/Telegram/SourceFiles/history.h b/Telegram/SourceFiles/history.h index b6119cd76..ecba44ef3 100644 --- a/Telegram/SourceFiles/history.h +++ b/Telegram/SourceFiles/history.h @@ -935,17 +935,6 @@ private: StylePtr _st; }; -class HistoryDependentItemCallback : public SharedCallback { -public: - HistoryDependentItemCallback(FullMsgId dependent) : _dependent(dependent) { - } - void call(ChannelData *channel, MsgId msgId) const override; - -private: - FullMsgId _dependent; - -}; - // any HistoryItem can have this Interface for // displaying the day mark above the message struct HistoryMessageDate : public BaseComponent { diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index ccf5631df..9b38e8eb5 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -101,6 +101,14 @@ public: constexpr int ScrollDateHideTimeout = 1000; +ApiWrap::RequestMessageDataCallback replyEditMessageDataCallback() { + return [](ChannelData *channel, MsgId msgId) { + if (App::main()) { + App::main()->messageDataReceived(channel, msgId); + } + }; +} + } // namespace // flick scroll taken from http://qt-project.org/doc/qt-4.8/demos-embedded-anomaly-src-flickcharm-cpp.html @@ -1684,7 +1692,7 @@ void HistoryInner::toggleScrollDateShown() { _scrollDateShown = !_scrollDateShown; auto from = _scrollDateShown ? 0. : 1.; auto to = _scrollDateShown ? 1. : 0.; - START_ANIMATION(_scrollDateOpacity, func(this, &HistoryInner::repaintScrollDateCallback), from, to, st::btnAttachEmoji.duration, anim::linear); + _scrollDateOpacity.start([this] { repaintScrollDateCallback(); }, from, to, st::btnAttachEmoji.duration); } void HistoryInner::repaintScrollDateCallback() { @@ -4117,7 +4125,7 @@ void HistoryWidget::applyDraft(bool parseLinks) { if (_editMsgId || _replyToId) { updateReplyEditTexts(); if (!_replyEditMsg && App::api()) { - App::api()->requestMessageData(_peer->asChannel(), _editMsgId ? _editMsgId : _replyToId, std_::make_unique()); + App::api()->requestMessageData(_peer->asChannel(), _editMsgId ? _editMsgId : _replyToId, replyEditMessageDataCallback()); } } } @@ -7633,7 +7641,7 @@ bool HistoryWidget::pinnedMsgVisibilityUpdated() { update(); } if (!_pinnedBar->msg && App::api()) { - App::api()->requestMessageData(_peer->asChannel(), _pinnedBar->msgId, std_::make_unique()); + App::api()->requestMessageData(_peer->asChannel(), _pinnedBar->msgId, replyEditMessageDataCallback()); } } else if (_pinnedBar) { destroyPinnedBar(); @@ -7652,12 +7660,6 @@ void HistoryWidget::destroyPinnedBar() { _inPinnedMsg = false; } -void HistoryWidget::ReplyEditMessageDataCallback::call(ChannelData *channel, MsgId msgId) const { - if (App::main()) { - App::main()->messageDataReceived(channel, msgId); - } -} - bool HistoryWidget::sendExistingDocument(DocumentData *doc, const QString &caption) { if (!_history || !doc || !canSendMessages(_peer)) { return false; diff --git a/Telegram/SourceFiles/historywidget.h b/Telegram/SourceFiles/historywidget.h index e87585120..ab8d8282c 100644 --- a/Telegram/SourceFiles/historywidget.h +++ b/Telegram/SourceFiles/historywidget.h @@ -908,11 +908,6 @@ private: void destroyPinnedBar(); void unpinDone(const MTPUpdates &updates); - class ReplyEditMessageDataCallback : public SharedCallback { - public: - void call(ChannelData *channel, MsgId msgId) const override; - }; - bool sendExistingDocument(DocumentData *doc, const QString &caption); void sendExistingPhoto(PhotoData *photo, const QString &caption); diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp b/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp index 06b1e07be..49a70a392 100644 --- a/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp +++ b/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp @@ -134,7 +134,9 @@ void Gif::paint(Painter &p, const QRect &clip, const PaintContext *context) cons bool loaded = document->loaded(), loading = document->loading(), displayLoading = document->displayLoading(); if (loaded && !gif() && _gif != Media::Clip::BadReader) { Gif *that = const_cast(this); - that->_gif = new Media::Clip::Reader(document->location(), document->data(), func(that, &Gif::clipCallback)); + that->_gif = new Media::Clip::Reader(document->location(), document->data(), [that](Media::Clip::Notification notification) { + that->clipCallback(notification); + }); if (gif()) _gif->setAutoplay(); } @@ -164,9 +166,9 @@ void Gif::paint(Painter &p, const QRect &clip, const PaintContext *context) cons } if (radial || (!_gif && !loaded && !loading) || (_gif == Media::Clip::BadReader)) { - float64 radialOpacity = (radial && loaded) ? _animation->radial.opacity() : 1; + auto radialOpacity = (radial && loaded) ? _animation->radial.opacity() : 1.; if (_animation && _animation->_a_over.animating(context->ms)) { - float64 over = _animation->_a_over.current(); + auto over = _animation->_a_over.current(); p.setOpacity((st::msgDateImgBg->c.alphaF() * (1 - over)) + (st::msgDateImgBgOver->c.alphaF() * over)); p.fillRect(r, st::black); } else { @@ -218,7 +220,7 @@ void Gif::clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) { bool wasactive = (_state & StateFlag::DeleteOver); if (active != wasactive) { auto from = active ? 0. : 1., to = active ? 1. : 0.; - START_ANIMATION(_a_deleteOver, func(this, &Gif::update), from, to, st::stickersRowDuration, anim::linear); + _a_deleteOver.start([this] { update(); }, from, to, st::stickersRowDuration); if (active) { _state |= StateFlag::DeleteOver; } else { @@ -232,7 +234,7 @@ void Gif::clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) { if (!getShownDocument()->loaded()) { ensureAnimation(); auto from = active ? 0. : 1., to = active ? 1. : 0.; - START_ANIMATION(_animation->_a_over, func(this, &Gif::update), from, to, st::stickersRowDuration, anim::linear); + _animation->_a_over.start([this] { update(); }, from, to, st::stickersRowDuration); } if (active) { _state |= StateFlag::Over; @@ -385,7 +387,7 @@ void Sticker::preload() const { void Sticker::paint(Painter &p, const QRect &clip, const PaintContext *context) const { bool loaded = getShownDocument()->loaded(); - float64 over = _a_over.isNull() ? (_active ? 1 : 0) : _a_over.current(); + auto over = _a_over.current(_active ? 1. : 0.); if (over > 0) { p.setOpacity(over); App::roundRect(p, QRect(QPoint(0, 0), st::stickerPanSize), st::emojiPanHover, StickerHoverCorners); @@ -414,7 +416,7 @@ void Sticker::clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) { _active = active; auto from = active ? 0. : 1., to = active ? 1. : 0.; - START_ANIMATION(_a_over, func(this, &Sticker::update), from, to, st::stickersRowDuration, anim::linear); + _a_over.start([this] { update(); }, from, to, st::stickersRowDuration); } } ItemBase::clickHandlerActiveChanged(p, active); diff --git a/Telegram/SourceFiles/layerwidget.cpp b/Telegram/SourceFiles/layerwidget.cpp index a5052f877..9c38039f1 100644 --- a/Telegram/SourceFiles/layerwidget.cpp +++ b/Telegram/SourceFiles/layerwidget.cpp @@ -638,7 +638,9 @@ QPixmap MediaPreviewWidget::currentImage() const { if (_document->loaded()) { if (!_gif && _gif != Media::Clip::BadReader) { auto that = const_cast(this); - that->_gif = new Media::Clip::Reader(_document->location(), _document->data(), func(that, &MediaPreviewWidget::clipCallback)); + that->_gif = new Media::Clip::Reader(_document->location(), _document->data(), [this, that](Media::Clip::Notification notification) { + that->clipCallback(notification); + }); if (gif()) _gif->setAutoplay(); } } diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index 45ea448aa..d96db84ee 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -4020,7 +4020,7 @@ DataIsLoadedResult allDataLoadedForMessage(const MTPMessage &msg) { void MainWidget::feedUpdates(const MTPUpdates &updates, uint64 randomId) { switch (updates.type()) { case mtpc_updates: { - const auto &d(updates.c_updates()); + auto &d = updates.c_updates(); if (d.vseq.v) { if (d.vseq.v <= updSeq) return; if (d.vseq.v > updSeq + 1) { @@ -4037,7 +4037,7 @@ void MainWidget::feedUpdates(const MTPUpdates &updates, uint64 randomId) { } break; case mtpc_updatesCombined: { - const auto &d(updates.c_updatesCombined()); + auto &d = updates.c_updatesCombined(); if (d.vseq_start.v) { if (d.vseq_start.v <= updSeq) return; if (d.vseq_start.v > updSeq + 1) { @@ -4054,15 +4054,14 @@ void MainWidget::feedUpdates(const MTPUpdates &updates, uint64 randomId) { } break; case mtpc_updateShort: { - const auto &d(updates.c_updateShort()); - + auto &d = updates.c_updateShort(); feedUpdate(d.vupdate); updSetState(0, d.vdate.v, updQts, updSeq); } break; case mtpc_updateShortMessage: { - const auto &d(updates.c_updateShortMessage()); + auto &d = updates.c_updateShortMessage(); if (!App::userLoaded(d.vuser_id.v) || (d.has_via_bot_id() && !App::userLoaded(d.vvia_bot_id.v)) || (d.has_entities() && !mentionUsersLoaded(d.ventities)) @@ -4076,7 +4075,7 @@ void MainWidget::feedUpdates(const MTPUpdates &updates, uint64 randomId) { // update before applying skipped MTPDmessage::Flags flags = mtpCastFlags(d.vflags.v) | MTPDmessage::Flag::f_from_id; - HistoryItem *item = App::histories().addNewMessage(MTP_message(MTP_flags(flags), d.vid, d.is_out() ? MTP_int(MTP::authedId()) : d.vuser_id, MTP_peerUser(d.is_out() ? d.vuser_id : MTP_int(MTP::authedId())), d.vfwd_from, d.vvia_bot_id, d.vreply_to_msg_id, d.vdate, d.vmessage, MTP_messageMediaEmpty(), MTPnullMarkup, d.has_entities() ? d.ventities : MTPnullEntities, MTPint(), MTPint()), NewMessageUnread); + auto item = App::histories().addNewMessage(MTP_message(MTP_flags(flags), d.vid, d.is_out() ? MTP_int(MTP::authedId()) : d.vuser_id, MTP_peerUser(d.is_out() ? d.vuser_id : MTP_int(MTP::authedId())), d.vfwd_from, d.vvia_bot_id, d.vreply_to_msg_id, d.vdate, d.vmessage, MTP_messageMediaEmpty(), MTPnullMarkup, d.has_entities() ? d.ventities : MTPnullEntities, MTPint(), MTPint()), NewMessageUnread); if (item) { _history->peerMessagesUpdated(item->history()->peer->id); } @@ -4087,7 +4086,7 @@ void MainWidget::feedUpdates(const MTPUpdates &updates, uint64 randomId) { } break; case mtpc_updateShortChatMessage: { - const auto &d(updates.c_updateShortChatMessage()); + auto &d = updates.c_updateShortChatMessage(); bool noFrom = !App::userLoaded(d.vfrom_id.v); if (!App::chatLoaded(d.vchat_id.v) || noFrom @@ -4104,7 +4103,7 @@ void MainWidget::feedUpdates(const MTPUpdates &updates, uint64 randomId) { // update before applying skipped MTPDmessage::Flags flags = mtpCastFlags(d.vflags.v) | MTPDmessage::Flag::f_from_id; - HistoryItem *item = App::histories().addNewMessage(MTP_message(MTP_flags(flags), d.vid, d.vfrom_id, MTP_peerChat(d.vchat_id), d.vfwd_from, d.vvia_bot_id, d.vreply_to_msg_id, d.vdate, d.vmessage, MTP_messageMediaEmpty(), MTPnullMarkup, d.has_entities() ? d.ventities : MTPnullEntities, MTPint(), MTPint()), NewMessageUnread); + auto item = App::histories().addNewMessage(MTP_message(MTP_flags(flags), d.vid, d.vfrom_id, MTP_peerChat(d.vchat_id), d.vfwd_from, d.vvia_bot_id, d.vreply_to_msg_id, d.vdate, d.vmessage, MTP_messageMediaEmpty(), MTPnullMarkup, d.has_entities() ? d.ventities : MTPnullEntities, MTPint(), MTPint()), NewMessageUnread); if (item) { _history->peerMessagesUpdated(item->history()->peer->id); } @@ -4115,7 +4114,7 @@ void MainWidget::feedUpdates(const MTPUpdates &updates, uint64 randomId) { } break; case mtpc_updateShortSentMessage: { - const auto &d(updates.c_updateShortSentMessage()); + auto &d = updates.c_updateShortSentMessage(); if (randomId) { PeerId peerId = 0; QString text; @@ -4125,7 +4124,7 @@ void MainWidget::feedUpdates(const MTPUpdates &updates, uint64 randomId) { if (peerId) { if (auto item = App::histItemById(peerToChannel(peerId), d.vid.v)) { if (d.has_entities() && !mentionUsersLoaded(d.ventities)) { - api()->requestMessageData(item->history()->peer->asChannel(), item->id, nullptr); + api()->requestMessageData(item->history()->peer->asChannel(), item->id, ApiWrap::RequestMessageDataCallback()); } auto entities = d.has_entities() ? entitiesFromMTP(d.ventities.c_vector().v) : EntitiesInText(); item->setText({ text, entities }); diff --git a/Telegram/SourceFiles/media/media_clip_reader.cpp b/Telegram/SourceFiles/media/media_clip_reader.cpp index 2ed2aa0e0..792cefaa4 100644 --- a/Telegram/SourceFiles/media/media_clip_reader.cpp +++ b/Telegram/SourceFiles/media/media_clip_reader.cpp @@ -180,8 +180,8 @@ void Reader::moveToNextWrite() const { void Reader::callback(Reader *reader, int32 threadIndex, Notification notification) { // check if reader is not deleted already - if (managers.size() > threadIndex && managers.at(threadIndex)->carries(reader)) { - reader->_callback.call(notification); + if (managers.size() > threadIndex && managers.at(threadIndex)->carries(reader) && reader->_callback) { + reader->_callback(notification); } } diff --git a/Telegram/SourceFiles/media/media_clip_reader.h b/Telegram/SourceFiles/media/media_clip_reader.h index 90dd5e3dd..220632c55 100644 --- a/Telegram/SourceFiles/media/media_clip_reader.h +++ b/Telegram/SourceFiles/media/media_clip_reader.h @@ -52,7 +52,7 @@ enum ReaderSteps { class ReaderPrivate; class Reader { public: - using Callback = Function; + using Callback = base::lambda_unique; enum class Mode { Gif, Video, diff --git a/Telegram/SourceFiles/media/view/media_clip_controller.cpp b/Telegram/SourceFiles/media/view/media_clip_controller.cpp index 796aee8cc..3e76932e1 100644 --- a/Telegram/SourceFiles/media/view/media_clip_controller.cpp +++ b/Telegram/SourceFiles/media/view/media_clip_controller.cpp @@ -41,8 +41,8 @@ Controller::Controller(QWidget *parent) : TWidget(parent) , _toPlayLeft(this, st::mediaviewPlayProgressLabel) , _fadeAnimation(std_::make_unique(this)) { _fadeAnimation->show(); - _fadeAnimation->setFinishedCallback(func(this, &Controller::fadeFinished)); - _fadeAnimation->setUpdatedCallback(func(this, &Controller::fadeUpdated)); + _fadeAnimation->setFinishedCallback([this] { fadeFinished(); }); + _fadeAnimation->setUpdatedCallback([this](float64 opacity) { fadeUpdated(opacity); }); _volumeController->setVolume(Global::VideoVolume()); diff --git a/Telegram/SourceFiles/media/view/media_clip_playback.cpp b/Telegram/SourceFiles/media/view/media_clip_playback.cpp index 6dfbaed15..b5b33e423 100644 --- a/Telegram/SourceFiles/media/view/media_clip_playback.cpp +++ b/Telegram/SourceFiles/media/view/media_clip_playback.cpp @@ -156,7 +156,7 @@ void Playback::setOver(bool over) { _over = over; auto from = _over ? 0. : 1., to = _over ? 1. : 0.; - START_ANIMATION(_a_over, func(this, &Playback::updateCallback), from, to, st::mediaviewOverDuration, anim::linear); + _a_over.start([this] { update(); }, from, to, st::mediaviewOverDuration); } } // namespace Clip diff --git a/Telegram/SourceFiles/media/view/media_clip_playback.h b/Telegram/SourceFiles/media/view/media_clip_playback.h index 190358d78..029c4503a 100644 --- a/Telegram/SourceFiles/media/view/media_clip_playback.h +++ b/Telegram/SourceFiles/media/view/media_clip_playback.h @@ -48,9 +48,6 @@ protected: private: void step_progress(float64 ms, bool timer); - void updateCallback() { - update(); - } void setOver(bool over); bool _over = false; diff --git a/Telegram/SourceFiles/media/view/media_clip_volume_controller.cpp b/Telegram/SourceFiles/media/view/media_clip_volume_controller.cpp index 8ffed03f2..c1b83746f 100644 --- a/Telegram/SourceFiles/media/view/media_clip_volume_controller.cpp +++ b/Telegram/SourceFiles/media/view/media_clip_volume_controller.cpp @@ -100,7 +100,7 @@ void VolumeController::setOver(bool over) { _over = over; auto from = _over ? 0. : 1., to = _over ? 1. : 0.; - START_ANIMATION(_a_over, func(this, &VolumeController::updateCallback), from, to, st::mediaviewOverDuration, anim::linear); + _a_over.start([this] { update(); }, from, to, st::mediaviewOverDuration); } } // namespace Clip diff --git a/Telegram/SourceFiles/media/view/media_clip_volume_controller.h b/Telegram/SourceFiles/media/view/media_clip_volume_controller.h index cf062ce09..69389eeab 100644 --- a/Telegram/SourceFiles/media/view/media_clip_volume_controller.h +++ b/Telegram/SourceFiles/media/view/media_clip_volume_controller.h @@ -43,9 +43,6 @@ protected: void leaveEvent(QEvent *e) override; private: - void updateCallback() { - update(); - } void setOver(bool over); void changeVolume(float64 newVolume); diff --git a/Telegram/SourceFiles/mediaview.cpp b/Telegram/SourceFiles/mediaview.cpp index 77eb491d7..8e4ea3e3c 100644 --- a/Telegram/SourceFiles/mediaview.cpp +++ b/Telegram/SourceFiles/mediaview.cpp @@ -1368,7 +1368,9 @@ void MediaView::createClipReader() { _current = _doc->thumb->pixNoCache(_doc->thumb->width(), _doc->thumb->height(), ImagePixSmooth | ImagePixBlurred, st::mvDocIconSize, st::mvDocIconSize); } auto mode = _doc->isVideo() ? Media::Clip::Reader::Mode::Video : Media::Clip::Reader::Mode::Gif; - _gif = std_::make_unique(_doc->location(), _doc->data(), func(this, &MediaView::clipCallback), mode); + _gif = std_::make_unique(_doc->location(), _doc->data(), [this](Media::Clip::Notification notification) { + clipCallback(notification); + }, mode); // Correct values will be set when gif gets inited. _videoPaused = _videoIsSilent = _videoStopped = false; @@ -1439,7 +1441,9 @@ void MediaView::restartVideoAtSeekPosition(int64 positionMs) { if (_current.isNull()) { _current = _gif->current(_gif->width(), _gif->height(), _gif->width(), _gif->height(), getms()); } - _gif = std_::make_unique(_doc->location(), _doc->data(), func(this, &MediaView::clipCallback), Media::Clip::Reader::Mode::Video, positionMs); + _gif = std_::make_unique(_doc->location(), _doc->data(), [this](Media::Clip::Notification notification) { + clipCallback(notification); + }, Media::Clip::Reader::Mode::Video, positionMs); // Correct values will be set when gif gets inited. _videoPaused = _videoIsSilent = _videoStopped = false; diff --git a/Telegram/SourceFiles/mtproto/file_download.h b/Telegram/SourceFiles/mtproto/file_download.h index 94b65fb2b..0d883504b 100644 --- a/Telegram/SourceFiles/mtproto/file_download.h +++ b/Telegram/SourceFiles/mtproto/file_download.h @@ -396,9 +396,10 @@ void reinitWebLoadManager(); void stopWebLoadManager(); namespace FileDownload { + namespace internal { -using ImageLoadedHandler = Function; +using ImageLoadedHandler = base::lambda_unique; Notify::ConnectionId plainRegisterImageLoadedObserver(ImageLoadedHandler &&handler); void notifyImageLoaded(); @@ -407,7 +408,9 @@ void notifyImageLoaded(); template void registerImageLoadedObserver(ObserverType *observer, void (ObserverType::*handler)()) { - auto connection = internal::plainRegisterImageLoadedObserver(func(observer, handler)); + auto connection = internal::plainRegisterImageLoadedObserver([observer, handler]() { + (observer->*handler)(); + }); Notify::observerRegistered(observer, connection); } diff --git a/Telegram/SourceFiles/observer_peer.h b/Telegram/SourceFiles/observer_peer.h index fe0e26cbc..aee59e5c3 100644 --- a/Telegram/SourceFiles/observer_peer.h +++ b/Telegram/SourceFiles/observer_peer.h @@ -91,14 +91,16 @@ void peerUpdatedSendDelayed(); namespace internal { -using PeerUpdateHandler = Function; +using PeerUpdateHandler = base::lambda_unique; ConnectionId plainRegisterPeerObserver(PeerUpdate::Flags events, PeerUpdateHandler &&handler); } // namespace internal template void registerPeerObserver(PeerUpdate::Flags events, ObserverType *observer, void (ObserverType::*handler)(const PeerUpdate &)) { - auto connection = internal::plainRegisterPeerObserver(events, func(observer, handler)); + auto connection = internal::plainRegisterPeerObserver(events, [observer, handler](const PeerUpdate &update) { + (observer->*handler)(update); + }); observerRegistered(observer, connection); } diff --git a/Telegram/SourceFiles/profile/profile_cover.cpp b/Telegram/SourceFiles/profile/profile_cover.cpp index 056b2f07c..16e2cb6cc 100644 --- a/Telegram/SourceFiles/profile/profile_cover.cpp +++ b/Telegram/SourceFiles/profile/profile_cover.cpp @@ -285,7 +285,7 @@ void CoverWidget::dragEnterEvent(QDragEnterEvent *e) { void CoverWidget::dragLeaveEvent(QDragLeaveEvent *e) { if (_dropArea && !_dropArea->hiding()) { - _dropArea->hideAnimated(func(this, &CoverWidget::dropAreaHidden)); + _dropArea->hideAnimated([this](CoverDropArea *area) { dropAreaHidden(area); }); } } @@ -306,7 +306,7 @@ void CoverWidget::dropEvent(QDropEvent *e) { } if (!_dropArea->hiding()) { - _dropArea->hideAnimated(func(this, &CoverWidget::dropAreaHidden)); + _dropArea->hideAnimated([this](CoverDropArea *area) { dropAreaHidden(area); }); } e->acceptProposedAction(); diff --git a/Telegram/SourceFiles/profile/profile_cover_drop_area.cpp b/Telegram/SourceFiles/profile/profile_cover_drop_area.cpp index e3370f66d..e23e8fc74 100644 --- a/Telegram/SourceFiles/profile/profile_cover_drop_area.cpp +++ b/Telegram/SourceFiles/profile/profile_cover_drop_area.cpp @@ -57,7 +57,9 @@ void CoverDropArea::paintEvent(QPaintEvent *e) { _cache = QPixmap(); if (_hiding) { hide(); - _hideFinishCallback.call(this); + if (_hideFinishCallback) { + _hideFinishCallback(this); + } return; } } @@ -93,7 +95,7 @@ void CoverDropArea::setupAnimation() { _cache = myGrab(this); } auto from = _hiding ? 1. : 0., to = _hiding ? 0. : 1.; - START_ANIMATION(_a_appearance, func(this, &CoverDropArea::refreshCallback), from, to, st::profileDropAreaDuration, anim::linear); + _a_appearance.start([this]() { update(); }, from, to, st::profileDropAreaDuration); } } // namespace Profile diff --git a/Telegram/SourceFiles/profile/profile_cover_drop_area.h b/Telegram/SourceFiles/profile/profile_cover_drop_area.h index 871523ff8..063e223ea 100644 --- a/Telegram/SourceFiles/profile/profile_cover_drop_area.h +++ b/Telegram/SourceFiles/profile/profile_cover_drop_area.h @@ -28,7 +28,7 @@ public: void showAnimated(); - using HideFinishCallback = Function; + using HideFinishCallback = base::lambda_unique; void hideAnimated(HideFinishCallback &&callback); bool hiding() const { @@ -39,9 +39,6 @@ protected: void paintEvent(QPaintEvent *e) override; private: - void refreshCallback() { - update(); - } void setupAnimation(); QString _title, _subtitle; diff --git a/Telegram/SourceFiles/profile/profile_info_widget.cpp b/Telegram/SourceFiles/profile/profile_info_widget.cpp index bbb62d9e2..032f6cd6f 100644 --- a/Telegram/SourceFiles/profile/profile_info_widget.cpp +++ b/Telegram/SourceFiles/profile/profile_info_widget.cpp @@ -149,15 +149,13 @@ void InfoWidget::refreshAbout() { textParseEntities(aboutText, TextParseLinks | TextParseMentions | TextParseHashtags | TextParseBotCommands, &aboutEntities); _about->setMarkedText({ aboutText, aboutEntities }); _about->setSelectable(true); - _about->setClickHandlerHook(func(this, &InfoWidget::aboutClickHandlerHook)); + _about->setClickHandlerHook([this](const ClickHandlerPtr &handler, Qt::MouseButton button) { + BotCommandClickHandler::setPeerForCommand(peer()); + return true; + }); } } -bool InfoWidget::aboutClickHandlerHook(const ClickHandlerPtr &handler, Qt::MouseButton button) { - BotCommandClickHandler::setPeerForCommand(peer()); - return true; -} - void InfoWidget::refreshMobileNumber() { TextWithEntities phoneText; if (auto user = peer()->asUser()) { diff --git a/Telegram/SourceFiles/profile/profile_info_widget.h b/Telegram/SourceFiles/profile/profile_info_widget.h index 16be5604b..37618ab77 100644 --- a/Telegram/SourceFiles/profile/profile_info_widget.h +++ b/Telegram/SourceFiles/profile/profile_info_widget.h @@ -51,8 +51,6 @@ private: void refreshChannelLink(); void refreshVisibility(); - bool aboutClickHandlerHook(const ClickHandlerPtr &handler, Qt::MouseButton button); - // labelWidget may be nullptr. void setLabeledText(ChildWidget *labelWidget, const QString &label, ChildWidget *textWidget, const TextWithEntities &textWithEntities, const QString ©Text); diff --git a/Telegram/SourceFiles/profile/profile_invite_link_widget.cpp b/Telegram/SourceFiles/profile/profile_invite_link_widget.cpp index f0a524578..294d4626b 100644 --- a/Telegram/SourceFiles/profile/profile_invite_link_widget.cpp +++ b/Telegram/SourceFiles/profile/profile_invite_link_widget.cpp @@ -99,19 +99,17 @@ void InviteLinkWidget::refreshLink() { _link->setMarkedText(linkData); _link->setSelectable(true); _link->setContextCopyText(QString()); - _link->setClickHandlerHook(func(this, &InviteLinkWidget::clickHandlerHook)); - } -} + _link->setClickHandlerHook([this](const ClickHandlerPtr &handler, Qt::MouseButton button) { + auto link = getInviteLink(); + if (link.isEmpty()) { + return true; + } -bool InviteLinkWidget::clickHandlerHook(const ClickHandlerPtr &handler, Qt::MouseButton button) { - auto link = getInviteLink(); - if (link.isEmpty()) { - return true; + QApplication::clipboard()->setText(link); + Ui::showLayer(new InformBox(lang(lng_group_invite_copied))); + return false; + }); } - - QApplication::clipboard()->setText(link); - Ui::showLayer(new InformBox(lang(lng_group_invite_copied))); - return false; } } // namespace Profile diff --git a/Telegram/SourceFiles/profile/profile_invite_link_widget.h b/Telegram/SourceFiles/profile/profile_invite_link_widget.h index 65ef20b71..e01c043ff 100644 --- a/Telegram/SourceFiles/profile/profile_invite_link_widget.h +++ b/Telegram/SourceFiles/profile/profile_invite_link_widget.h @@ -46,8 +46,6 @@ private: void refreshLink(); void refreshVisibility(); - bool clickHandlerHook(const ClickHandlerPtr &handler, Qt::MouseButton button); - ChildWidget _link = { nullptr }; }; diff --git a/Telegram/SourceFiles/profile/profile_members_widget.cpp b/Telegram/SourceFiles/profile/profile_members_widget.cpp index 472c1b64d..78db1d3c9 100644 --- a/Telegram/SourceFiles/profile/profile_members_widget.cpp +++ b/Telegram/SourceFiles/profile/profile_members_widget.cpp @@ -315,17 +315,15 @@ void MembersWidget::refreshLimitReached() { QString link = textRichPrepare(lang(lng_profile_migrate_learn_more)); QString text = qsl("%1%2%3\n%4 [a href=\"https://telegram.org/blog/supergroups5k\"]%5[/a]").arg(textcmdStartSemibold()).arg(title).arg(textcmdStopSemibold()).arg(body).arg(link); _limitReachedInfo->setRichText(text); - _limitReachedInfo->setClickHandlerHook(func(this, &MembersWidget::limitReachedHook)); + _limitReachedInfo->setClickHandlerHook([this](const ClickHandlerPtr &handler, Qt::MouseButton button) { + Ui::showLayer(new ConvertToSupergroupBox(peer()->asChat())); + return false; + }); } else if (!limitReachedShown && _limitReachedInfo) { _limitReachedInfo.destroy(); } } -bool MembersWidget::limitReachedHook(const ClickHandlerPtr &handler, Qt::MouseButton button) { - Ui::showLayer(new ConvertToSupergroupBox(peer()->asChat())); - return false; -} - void MembersWidget::checkSelfAdmin(ChatData *chat) { if (chat->participants.isEmpty()) return; diff --git a/Telegram/SourceFiles/profile/profile_userpic_button.cpp b/Telegram/SourceFiles/profile/profile_userpic_button.cpp index 048777f1b..e1b92dedb 100644 --- a/Telegram/SourceFiles/profile/profile_userpic_button.cpp +++ b/Telegram/SourceFiles/profile/profile_userpic_button.cpp @@ -45,7 +45,7 @@ void UserpicButton::showFinished() { _notShownYet = false; if (!_waiting) { _a_appearance.finish(); - START_ANIMATION(_a_appearance, func(this, &UserpicButton::refreshCallback), 0, 1, st::profilePhotoDuration, anim::linear); + _a_appearance.start([this] { update(); }, 0, 1, st::profilePhotoDuration); } } } @@ -100,7 +100,7 @@ void UserpicButton::startNewPhotoShowing() { } _a_appearance.finish(); - START_ANIMATION(_a_appearance, func(this, &UserpicButton::refreshCallback), 0, 1, st::profilePhotoDuration, anim::linear); + _a_appearance.start([this] { update(); }, 0, 1, st::profilePhotoDuration); update(); } diff --git a/Telegram/SourceFiles/profile/profile_userpic_button.h b/Telegram/SourceFiles/profile/profile_userpic_button.h index 8dc63b1f6..cd75d80a4 100644 --- a/Telegram/SourceFiles/profile/profile_userpic_button.h +++ b/Telegram/SourceFiles/profile/profile_userpic_button.h @@ -43,10 +43,6 @@ private: void notifyPeerUpdated(const Notify::PeerUpdate &update); void notifyImageLoaded(); - void refreshCallback() { - update(); - } - void processPeerPhoto(); void processNewPeerPhoto(); void startNewPhotoShowing(); diff --git a/Telegram/SourceFiles/settings/settings_cover.cpp b/Telegram/SourceFiles/settings/settings_cover.cpp index 11047c067..50d57b299 100644 --- a/Telegram/SourceFiles/settings/settings_cover.cpp +++ b/Telegram/SourceFiles/settings/settings_cover.cpp @@ -217,7 +217,7 @@ void CoverWidget::dragEnterEvent(QDragEnterEvent *e) { void CoverWidget::dragLeaveEvent(QDragLeaveEvent *e) { if (_dropArea && !_dropArea->hiding()) { - _dropArea->hideAnimated(func(this, &CoverWidget::dropAreaHidden)); + _dropArea->hideAnimated([this](Profile::CoverDropArea *area) { dropAreaHidden(area); }); } } @@ -228,7 +228,7 @@ void CoverWidget::dropEvent(QDropEvent *e) { if (mimeData->hasImage()) { img = qvariant_cast(mimeData->imageData()); } else { - const auto &urls = mimeData->urls(); + auto &urls = mimeData->urls(); if (urls.size() == 1) { auto &url = urls.at(0); if (url.isLocalFile()) { @@ -238,7 +238,7 @@ void CoverWidget::dropEvent(QDropEvent *e) { } if (!_dropArea->hiding()) { - _dropArea->hideAnimated(func(this, &CoverWidget::dropAreaHidden)); + _dropArea->hideAnimated([this](Profile::CoverDropArea *area) { dropAreaHidden(area); }); } e->acceptProposedAction(); diff --git a/Telegram/SourceFiles/settings/settings_info_widget.cpp b/Telegram/SourceFiles/settings/settings_info_widget.cpp index 88acf95b4..28219a858 100644 --- a/Telegram/SourceFiles/settings/settings_info_widget.cpp +++ b/Telegram/SourceFiles/settings/settings_info_widget.cpp @@ -81,7 +81,10 @@ void InfoWidget::refreshUsername() { usernameText.entities.push_back(EntityInText(EntityInTextCustomUrl, 0, usernameText.text.size(), qsl("https://telegram.me/") + self()->username)); setLabeledText(_username, lang(lng_profile_username), usernameText, TextWithEntities(), copyText); if (auto text = _username->entity()->textLabel()) { - text->setClickHandlerHook(func(this, &InfoWidget::usernameClickHandlerHook)); + text->setClickHandlerHook([](const ClickHandlerPtr &handler, Qt::MouseButton button) { + Ui::showLayer(new UsernameBox()); + return false; + }); } } @@ -96,19 +99,20 @@ void InfoWidget::refreshLink() { } setLabeledText(_link, lang(lng_profile_link), linkText, linkTextShort, QString()); if (auto text = _link->entity()->textLabel()) { - text->setClickHandlerHook(func(this, &InfoWidget::usernameClickHandlerHook)); + text->setClickHandlerHook([](const ClickHandlerPtr &handler, Qt::MouseButton button) { + Ui::showLayer(new UsernameBox()); + return false; + }); } if (auto shortText = _link->entity()->shortTextLabel()) { shortText->setExpandLinksMode(ExpandLinksUrlOnly); - shortText->setClickHandlerHook(func(this, &InfoWidget::usernameClickHandlerHook)); + shortText->setClickHandlerHook([](const ClickHandlerPtr &handler, Qt::MouseButton button) { + Ui::showLayer(new UsernameBox()); + return false; + }); } } -bool InfoWidget::usernameClickHandlerHook(const ClickHandlerPtr &handler, Qt::MouseButton button) { - Ui::showLayer(new UsernameBox()); - return false; -} - void InfoWidget::setLabeledText(ChildWidget &row, const QString &label, const TextWithEntities &textWithEntities, const TextWithEntities &shortTextWithEntities, const QString ©Text) { if (textWithEntities.text.isEmpty()) { row->slideUp(); diff --git a/Telegram/SourceFiles/settings/settings_info_widget.h b/Telegram/SourceFiles/settings/settings_info_widget.h index 6ffdc791d..52a6f2b05 100644 --- a/Telegram/SourceFiles/settings/settings_info_widget.h +++ b/Telegram/SourceFiles/settings/settings_info_widget.h @@ -38,8 +38,6 @@ private: // Observed notifications. void notifyPeerUpdated(const Notify::PeerUpdate &update); - bool usernameClickHandlerHook(const ClickHandlerPtr &handler, Qt::MouseButton button); - void createControls(); void refreshControls(); void refreshMobileNumber(); diff --git a/Telegram/SourceFiles/ui/animation.cpp b/Telegram/SourceFiles/ui/animation.cpp index 3f6d97a37..83e3bc729 100644 --- a/Telegram/SourceFiles/ui/animation.cpp +++ b/Telegram/SourceFiles/ui/animation.cpp @@ -120,7 +120,7 @@ AnimationManager::AnimationManager() : _timer(this), _iterating(false) { void AnimationManager::start(Animation *obj) { if (_iterating) { - _starting.insert(obj, NullType()); + _starting.insert(obj); if (!_stopping.isEmpty()) { _stopping.remove(obj); } @@ -128,21 +128,21 @@ void AnimationManager::start(Animation *obj) { if (_objects.isEmpty()) { _timer.start(AnimationTimerDelta); } - _objects.insert(obj, NullType()); + _objects.insert(obj); } } void AnimationManager::stop(Animation *obj) { if (_iterating) { - _stopping.insert(obj, NullType()); + _stopping.insert(obj); if (!_starting.isEmpty()) { _starting.remove(obj); } } else { - AnimatingObjects::iterator i = _objects.find(obj); + auto i = _objects.find(obj); if (i != _objects.cend()) { _objects.erase(i); - if (_objects.isEmpty()) { + if (_objects.empty()) { _timer.stop(); } } @@ -152,26 +152,26 @@ void AnimationManager::stop(Animation *obj) { void AnimationManager::timeout() { _iterating = true; uint64 ms = getms(); - for (AnimatingObjects::const_iterator i = _objects.begin(), e = _objects.end(); i != e; ++i) { - if (!_stopping.contains(i.key())) { - i.key()->step(ms, true); + for_const (auto object, _objects) { + if (!_stopping.contains(object)) { + object->step(ms, true); } } _iterating = false; if (!_starting.isEmpty()) { - for (AnimatingObjects::iterator i = _starting.begin(), e = _starting.end(); i != e; ++i) { - _objects.insert(i.key(), NullType()); + for_const (auto object, _starting) { + _objects.insert(object); } _starting.clear(); } if (!_stopping.isEmpty()) { - for (AnimatingObjects::iterator i = _stopping.begin(), e = _stopping.end(); i != e; ++i) { - _objects.remove(i.key()); + for_const (auto object, _stopping) { + _objects.remove(object); } _stopping.clear(); } - if (!_objects.size()) { + if (_objects.empty()) { _timer.stop(); } } diff --git a/Telegram/SourceFiles/ui/animation.h b/Telegram/SourceFiles/ui/animation.h index 8fc5201cf..4130012c6 100644 --- a/Telegram/SourceFiles/ui/animation.h +++ b/Telegram/SourceFiles/ui/animation.h @@ -21,6 +21,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #pragma once #include "core/basic_types.h" +#include "core/lambda_wrap.h" #include #include @@ -57,6 +58,7 @@ namespace anim { class fvalue { // float animated value public: + using ValueType = float64; fvalue() { } @@ -88,15 +90,14 @@ namespace anim { _delta = 0; } - typedef float64 Type; - private: - float64 _cur, _from, _delta; + }; class ivalue { // int animated value public: + using ValueType = int32; ivalue() { } @@ -128,16 +129,15 @@ namespace anim { _delta = 0; } - typedef int32 Type; - private: - int32 _cur; float64 _from, _delta; + }; class cvalue { // QColor animated value public: + using ValueType = QColor; cvalue() { } @@ -199,12 +199,10 @@ namespace anim { _delta_r = _delta_g = _delta_b = _delta_a = 0; } - typedef QColor Type; - private: - QColor _cur; float64 _from_r, _from_g, _from_b, _from_a, _delta_r, _delta_g, _delta_b, _delta_a; + }; void startManager(); @@ -380,105 +378,81 @@ AnimationCallbacks animation(Param param, Type *obj, typename AnimationCallbacks template class SimpleAnimation { public: - using Callback = Function; + using ValueType = typename AnimType::ValueType; + using Callback = base::lambda_unique; - SimpleAnimation() { + bool animating() const { + if (_data) { + if (_data->a_animation.animating()) { + return true; + } + _data.reset(); + } + return false; } - bool animating(uint64 ms) { - if (_data && _data->_a.animating()) { - _data->_a.step(ms); - return _data && _data->_a.animating(); + if (animating()) { + _data->a_animation.step(ms); + return animating(); } return false; } - bool isNull() const { - return !_data; + ValueType current() const { + t_assert(_data != nullptr); + return _data->value.current(); } - - typename AnimType::Type current() { - return _data ? _data->a.current() : typename AnimType::Type(); + ValueType current(const ValueType &def) const { + return _data ? current() : def; } - - typename AnimType::Type current(const typename AnimType::Type &def) { - return _data ? _data->a.current() : def; - } - - typename AnimType::Type current(uint64 ms, const typename AnimType::Type &def) { + ValueType current(uint64 ms, const ValueType &def) { return animating(ms) ? current() : def; } - void setup(const typename AnimType::Type &from, Callback &&update) { + template + void start(Lambda &&updateCallback, const ValueType &from, const ValueType &to, float64 duration, anim::transition transition = anim::linear) { if (!_data) { - _data = new Data(from, std_::move(update), animation(this, &SimpleAnimation::step)); - } else { - _data->a = AnimType(from, from); - } - } - - void start(const typename AnimType::Type &to, float64 duration, anim::transition transition = anim::linear) { - if (_data) { - _data->a.start(to); - _data->_a.start(); - _data->duration = duration; - _data->transition = transition; + _data = std_::make_unique(from, std_::move(updateCallback)); } + _data->value.start(to); + _data->duration = duration; + _data->transition = transition; + _data->a_animation.start(); } void finish() { - if (isNull()) { - return; + if (_data) { + _data->value.finish(); + _data->a_animation.stop(); + _data.reset(); } - - _data->a.finish(); - _data->_a.stop(); - delete _data; - _data = nullptr; - } - - ~SimpleAnimation() { - deleteAndMark(_data); } private: struct Data { - Data(const typename AnimType::Type &from, Callback &&update, AnimationCallbacks &&acb) - : a(from, from) - , _a(std_::move(acb)) - , update(std_::move(update)) - , duration(0) - , transition(anim::linear) { + Data(const ValueType &from, Callback &&updateCallback) + : value(from, from) + , a_animation(animation(this, &Data::step)) + , updateCallback(std_::move(updateCallback)) { } - AnimType a; - Animation _a; - Callback update; - float64 duration; - anim::transition transition; + void step(float64 ms, bool timer) { + auto dt = (ms >= duration) ? 1. : (ms / duration); + if (dt >= 1) { + value.finish(); + a_animation.stop(); + } else { + value.update(dt, transition); + } + updateCallback(); + } + + AnimType value; + Animation a_animation; + Callback updateCallback; + float64 duration = 0.; + anim::transition transition = anim::linear; }; - Data *_data = nullptr; - - void step(float64 ms, bool timer) { - float64 dt = (ms >= _data->duration) ? 1 : (ms / _data->duration); - if (dt >= 1) { - _data->a.finish(); - _data->_a.stop(); - } else { - _data->a.update(dt, _data->transition); - } - - Callback callbackCache, *toCall = &_data->update; - if (!_data->_a.animating()) { - callbackCache = std_::move(_data->update); - toCall = &callbackCache; - - delete _data; - _data = nullptr; - } - if (timer) { - toCall->call(); - } - } + mutable std_::unique_ptr _data; }; @@ -486,18 +460,8 @@ using FloatAnimation = SimpleAnimation; using IntAnimation = SimpleAnimation; using ColorAnimation = SimpleAnimation; -// Macro allows us to lazily create updateCallback. -#define ENSURE_ANIMATION(animation, updateCallback, from) \ -if ((animation).isNull()) { \ - (animation).setup((from), (updateCallback)); \ -} - -#define START_ANIMATION(animation, updateCallback, from, to, duration, transition) \ -ENSURE_ANIMATION(animation, updateCallback, from); \ -(animation).start((to), (duration), (transition)) - class AnimationManager : public QObject { -Q_OBJECT + Q_OBJECT public: AnimationManager(); @@ -511,7 +475,7 @@ public slots: void clipCallback(Media::Clip::Reader *reader, qint32 threadIndex, qint32 notification); private: - typedef QMap AnimatingObjects; + using AnimatingObjects = OrderedSet; AnimatingObjects _objects, _starting, _stopping; QTimer _timer; bool _iterating; diff --git a/Telegram/SourceFiles/ui/buttons/history_down_button.cpp b/Telegram/SourceFiles/ui/buttons/history_down_button.cpp index 2b1fd86e9..773742426 100644 --- a/Telegram/SourceFiles/ui/buttons/history_down_button.cpp +++ b/Telegram/SourceFiles/ui/buttons/history_down_button.cpp @@ -118,7 +118,7 @@ void HistoryDownButton::hideAnimated() { void HistoryDownButton::toggleAnimated() { _shown = !_shown; float64 from = _shown ? 0. : 1., to = _shown ? 1. : 0.; - START_ANIMATION(_a_show, func(this, &HistoryDownButton::repaintCallback), from, to, st::btnAttachEmoji.duration, anim::linear); + _a_show.start([this] { update(); }, from, to, st::btnAttachEmoji.duration); } void HistoryDownButton::finishAnimation() { diff --git a/Telegram/SourceFiles/ui/buttons/history_down_button.h b/Telegram/SourceFiles/ui/buttons/history_down_button.h index 43dbd098c..8030a905e 100644 --- a/Telegram/SourceFiles/ui/buttons/history_down_button.h +++ b/Telegram/SourceFiles/ui/buttons/history_down_button.h @@ -47,9 +47,6 @@ protected: private: void toggleAnimated(); - void repaintCallback() { - update(); - } void step_arrowOver(float64 ms, bool timer); QPixmap _cache; diff --git a/Telegram/SourceFiles/ui/buttons/icon_button.cpp b/Telegram/SourceFiles/ui/buttons/icon_button.cpp index 43498c7cc..2a562d289 100644 --- a/Telegram/SourceFiles/ui/buttons/icon_button.cpp +++ b/Telegram/SourceFiles/ui/buttons/icon_button.cpp @@ -49,7 +49,7 @@ void IconButton::onStateChanged(int oldState, ButtonStateChangeSource source) { if (over != (oldState & StateOver)) { auto from = over ? 0. : 1.; auto to = over ? 1. : 0.; - START_ANIMATION(_a_over, func(this, &IconButton::updateCallback), from, to, _st.duration, anim::linear); + _a_over.start([this] { update(); }, from, to, _st.duration); } } diff --git a/Telegram/SourceFiles/ui/buttons/icon_button.h b/Telegram/SourceFiles/ui/buttons/icon_button.h index 758c59567..488a49df1 100644 --- a/Telegram/SourceFiles/ui/buttons/icon_button.h +++ b/Telegram/SourceFiles/ui/buttons/icon_button.h @@ -37,10 +37,6 @@ protected: void onStateChanged(int oldState, ButtonStateChangeSource source) override; private: - void updateCallback() { - update(); - } - const style::IconButton &_st; const style::icon *_iconOverride = nullptr; diff --git a/Telegram/SourceFiles/ui/effects/fade_animation.cpp b/Telegram/SourceFiles/ui/effects/fade_animation.cpp index 9936c51e5..5e2663a5d 100644 --- a/Telegram/SourceFiles/ui/effects/fade_animation.cpp +++ b/Telegram/SourceFiles/ui/effects/fade_animation.cpp @@ -65,7 +65,9 @@ void FadeAnimation::stopAnimation() { _cache = QPixmap(); updateCallback(); _widget->showChildren(); - _finishedCallback.call(); + if (_finishedCallback) { + _finishedCallback(); + } } if (_visible == _widget->isHidden()) { _widget->setVisible(_visible); @@ -91,7 +93,9 @@ void FadeAnimation::startAnimation(int duration) { _cache = myGrab(_widget); _widget->hideChildren(); } - START_ANIMATION(_animation, func(this, &FadeAnimation::updateCallback), _visible ? 0. : 1., _visible ? 1. : 0., duration, anim::linear); + auto from = _visible ? 0. : 1.; + auto to = _visible ? 1. : 0.; + _animation.start([this]() { updateCallback(); }, from, to, duration); updateCallback(); if (_widget->isHidden()) { _widget->show(); @@ -101,7 +105,9 @@ void FadeAnimation::startAnimation(int duration) { void FadeAnimation::updateCallback() { if (_animation.animating(getms())) { _widget->update(); - _updatedCallback.call(_animation.current()); + if (_updatedCallback) { + _updatedCallback(_animation.current(_visible ? 1. : 0.)); + } } else { stopAnimation(); } diff --git a/Telegram/SourceFiles/ui/effects/fade_animation.h b/Telegram/SourceFiles/ui/effects/fade_animation.h index aaf95129f..4ed09de04 100644 --- a/Telegram/SourceFiles/ui/effects/fade_animation.h +++ b/Telegram/SourceFiles/ui/effects/fade_animation.h @@ -31,10 +31,10 @@ public: bool paint(Painter &p); void refreshCache(); - using FinishedCallback = Function; + using FinishedCallback = base::lambda_unique; void setFinishedCallback(FinishedCallback &&callback); - using UpdatedCallback = Function; + using UpdatedCallback = base::lambda_unique; void setUpdatedCallback(UpdatedCallback &&callback); void show(); diff --git a/Telegram/SourceFiles/ui/filedialog.h b/Telegram/SourceFiles/ui/filedialog.h index c3d774294..a73b97603 100644 --- a/Telegram/SourceFiles/ui/filedialog.h +++ b/Telegram/SourceFiles/ui/filedialog.h @@ -65,14 +65,16 @@ bool processQuery(); namespace internal { -using QueryUpdateHandler = Function; +using QueryUpdateHandler = base::lambda_unique; Notify::ConnectionId plainRegisterObserver(QueryUpdateHandler &&handler); } // namespace internal template void registerObserver(ObserverType *observer, void (ObserverType::*handler)(const QueryUpdate &)) { - auto connection = internal::plainRegisterObserver(func(observer, handler)); + auto connection = internal::plainRegisterObserver([observer, handler](const QueryUpdate &update) { + (observer->*handler)(update); + }); Notify::observerRegistered(observer, connection); } diff --git a/Telegram/SourceFiles/ui/flatbutton.cpp b/Telegram/SourceFiles/ui/flatbutton.cpp index 3ed82ca7b..167d30f86 100644 --- a/Telegram/SourceFiles/ui/flatbutton.cpp +++ b/Telegram/SourceFiles/ui/flatbutton.cpp @@ -332,7 +332,7 @@ void EmojiButton::setLoading(bool loading) { if (_loading != loading) { _loading = loading; auto from = loading ? 0. : 1., to = loading ? 1. : 0.; - START_ANIMATION(a_loading, func(this, &EmojiButton::updateCallback), from, to, st::emojiCircleDuration, anim::linear); + a_loading.start([this] { update(); }, from, to, st::emojiCircleDuration); if (loading) { _a_loading.start(); } else { diff --git a/Telegram/SourceFiles/ui/flatbutton.h b/Telegram/SourceFiles/ui/flatbutton.h index 83d725615..090b3232f 100644 --- a/Telegram/SourceFiles/ui/flatbutton.h +++ b/Telegram/SourceFiles/ui/flatbutton.h @@ -147,12 +147,9 @@ private: void step_loading(uint64 ms, bool timer) { if (timer) { - updateCallback(); + update(); } } - void updateCallback() { - update(); - } }; diff --git a/Telegram/SourceFiles/ui/flatlabel.cpp b/Telegram/SourceFiles/ui/flatlabel.cpp index e879861d5..909f4e172 100644 --- a/Telegram/SourceFiles/ui/flatlabel.cpp +++ b/Telegram/SourceFiles/ui/flatlabel.cpp @@ -232,7 +232,7 @@ Text::StateResult FlatLabel::dragActionFinish(const QPoint &p, Qt::MouseButton b _selectionType = TextSelectType::Letters; if (activated) { - if (_clickHandlerHook.isNull() || _clickHandlerHook.call(activated, button)) { + if (!_clickHandlerHook || _clickHandlerHook(activated, button)) { App::activateClickHandler(activated, button); } } diff --git a/Telegram/SourceFiles/ui/flatlabel.h b/Telegram/SourceFiles/ui/flatlabel.h index 978622b79..24e5a3942 100644 --- a/Telegram/SourceFiles/ui/flatlabel.h +++ b/Telegram/SourceFiles/ui/flatlabel.h @@ -47,7 +47,7 @@ public: void setLink(uint16 lnkIndex, const ClickHandlerPtr &lnk); - using ClickHandlerHook = Function; + using ClickHandlerHook = base::lambda_unique; void setClickHandlerHook(ClickHandlerHook &&hook); // ClickHandlerHost interface diff --git a/Telegram/SourceFiles/ui/inner_dropdown.cpp b/Telegram/SourceFiles/ui/inner_dropdown.cpp index ad6ccf238..8065c18e0 100644 --- a/Telegram/SourceFiles/ui/inner_dropdown.cpp +++ b/Telegram/SourceFiles/ui/inner_dropdown.cpp @@ -160,12 +160,12 @@ void InnerDropdown::onHideStart() { void InnerDropdown::startAnimation() { auto from = _hiding ? 1. : 0.; auto to = _hiding ? 0. : 1.; - if (_a_appearance.isNull()) { + if (!_a_appearance.animating()) { showChildren(); _cache = myGrab(this); } hideChildren(); - START_ANIMATION(_a_appearance, func(this, &InnerDropdown::repaintCallback), from, to, _st.duration, anim::linear); + _a_appearance.start([this] { repaintCallback(); }, from, to, _st.duration); } void InnerDropdown::hidingFinished() { @@ -186,7 +186,7 @@ void InnerDropdown::showingStarted() { void InnerDropdown::repaintCallback() { update(); - if (!_a_appearance.animating(getms()) && _hiding) { + if (!_a_appearance.animating() && _hiding) { _hiding = false; hidingFinished(); } diff --git a/Telegram/SourceFiles/ui/inner_dropdown.h b/Telegram/SourceFiles/ui/inner_dropdown.h index 55974f78e..56f28caec 100644 --- a/Telegram/SourceFiles/ui/inner_dropdown.h +++ b/Telegram/SourceFiles/ui/inner_dropdown.h @@ -35,7 +35,7 @@ public: void setOwnedWidget(ScrolledWidget *widget); bool overlaps(const QRect &globalRect) { - if (isHidden() || !_a_appearance.isNull()) return false; + if (isHidden() || _a_appearance.animating()) return false; return rect().marginsRemoved(_st.padding).contains(QRect(mapFromGlobal(globalRect.topLeft()), globalRect.size())); } diff --git a/Telegram/SourceFiles/ui/twidget.cpp b/Telegram/SourceFiles/ui/twidget.cpp index 2bfac39d8..20053a7b5 100644 --- a/Telegram/SourceFiles/ui/twidget.cpp +++ b/Telegram/SourceFiles/ui/twidget.cpp @@ -86,7 +86,7 @@ enum class Mode { }; void ToggleableShadow::setMode(Mode mode) { if (mode == Mode::ShownFast || mode == Mode::HiddenFast) { - if (!_a_opacity.isNull()) { + if (!_a_opacity.animating()) { _a_opacity.finish(); update(); } @@ -94,18 +94,12 @@ void ToggleableShadow::setMode(Mode mode) { if (_shown && (mode == Mode::Hidden || mode == Mode::HiddenFast)) { _shown = false; if (mode == Mode::Hidden) { - if (_a_opacity.isNull()) { - _a_opacity.setup(1., func(this, &ToggleableShadow::repaintCallback)); - } - _a_opacity.start(0., st::shadowToggleDuration); + _a_opacity.start([this] { update(); }, 1., 0., st::shadowToggleDuration); } } else if (!_shown && (mode == Mode::Shown || mode == Mode::ShownFast)) { _shown = true; if (mode == Mode::Shown) { - if (_a_opacity.isNull()) { - _a_opacity.setup(0., func(this, &ToggleableShadow::repaintCallback)); - } - _a_opacity.start(1., st::shadowToggleDuration); + _a_opacity.start([this] { update(); }, 0., 1., st::shadowToggleDuration); } } } diff --git a/Telegram/SourceFiles/ui/twidget.h b/Telegram/SourceFiles/ui/twidget.h index b12c4da1b..0dc17700b 100644 --- a/Telegram/SourceFiles/ui/twidget.h +++ b/Telegram/SourceFiles/ui/twidget.h @@ -268,17 +268,13 @@ public: void setMode(Mode mode); bool isFullyShown() const { - return _shown && _a_opacity.isNull(); + return _shown && !_a_opacity.animating(); } protected: void paintEvent(QPaintEvent *e) override; private: - void repaintCallback() { - update(); - } - const style::color &_color; FloatAnimation _a_opacity; bool _shown = true; diff --git a/Telegram/SourceFiles/window/section_widget.cpp b/Telegram/SourceFiles/window/section_widget.cpp index 47c085446..a1f13eed2 100644 --- a/Telegram/SourceFiles/window/section_widget.cpp +++ b/Telegram/SourceFiles/window/section_widget.cpp @@ -50,8 +50,8 @@ void SectionWidget::showAnimated(SlideDirection direction, const SectionSlidePar _showAnimation = std_::make_unique(); _showAnimation->setDirection(direction); - _showAnimation->setRepaintCallback(func(this, &SectionWidget::repaintCallback)); - _showAnimation->setFinishedCallback(func(this, &SectionWidget::showFinished)); + _showAnimation->setRepaintCallback([this] { update(); }); + _showAnimation->setFinishedCallback([this] { showFinished(); }); _showAnimation->setPixmaps(params.oldContentCache, myContentCache); _showAnimation->setTopBarShadow(params.withTopBarShadow); _showAnimation->start(); diff --git a/Telegram/SourceFiles/window/section_widget.h b/Telegram/SourceFiles/window/section_widget.h index b77377fbe..ca72b0dd7 100644 --- a/Telegram/SourceFiles/window/section_widget.h +++ b/Telegram/SourceFiles/window/section_widget.h @@ -89,10 +89,6 @@ protected: } private: - // QWidget::update() method is overloaded and we need template deduction. - void repaintCallback() { - update(); - } void showFinished(); std_::unique_ptr _showAnimation; diff --git a/Telegram/SourceFiles/window/slide_animation.cpp b/Telegram/SourceFiles/window/slide_animation.cpp index 5f53e98fa..fb9ab988e 100644 --- a/Telegram/SourceFiles/window/slide_animation.cpp +++ b/Telegram/SourceFiles/window/slide_animation.cpp @@ -92,7 +92,9 @@ void SlideAnimation::step(float64 ms, bool timer) { a_coordUnder.finish(); a_coordOver.finish(); - _finishedCallback.call(); + if (_finishedCallback) { + _finishedCallback(); + } return; } } @@ -100,8 +102,8 @@ void SlideAnimation::step(float64 ms, bool timer) { a_coordUnder.update(dt, st::slideFunction); a_coordOver.update(dt, st::slideFunction); a_progress.update(dt, st::slideFunction); - if (timer) { - _repaintCallback.call(); + if (timer && _repaintCallback) { + _repaintCallback(); } } diff --git a/Telegram/SourceFiles/window/slide_animation.h b/Telegram/SourceFiles/window/slide_animation.h index 5ce4068ae..53a24c3b6 100644 --- a/Telegram/SourceFiles/window/slide_animation.h +++ b/Telegram/SourceFiles/window/slide_animation.h @@ -37,10 +37,10 @@ public: void setPixmaps(const QPixmap &oldContentCache, const QPixmap &newContentCache); void setTopBarShadow(bool enabled); - using RepaintCallback = Function; + using RepaintCallback = base::lambda_unique; void setRepaintCallback(RepaintCallback &&callback); - using FinishedCallback = Function; + using FinishedCallback = base::lambda_unique; void setFinishedCallback(FinishedCallback &&callback); void start();