From d014b47958dd5a4cde14cf67ca9ca8b86faf06ee Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 27 Nov 2017 15:43:57 +0400 Subject: [PATCH] Move Info::TopBarOverride to Info::TopBar. This allows to improve animations in shared media items selection. --- Telegram/SourceFiles/base/unique_qptr.h | 51 ++-- Telegram/SourceFiles/boxes/stickers_box.cpp | 2 +- .../chat_helpers/gifs_list_widget.cpp | 4 +- .../SourceFiles/dialogs/dialogs_widget.cpp | 6 +- .../history/history_admin_log_section.cpp | 6 +- Telegram/SourceFiles/info/info.style | 2 + Telegram/SourceFiles/info/info_top_bar.cpp | 266 ++++++++++-------- Telegram/SourceFiles/info/info_top_bar.h | 19 +- .../info/info_top_bar_override.cpp | 174 ------------ .../SourceFiles/info/info_top_bar_override.h | 77 ----- .../info/media/info_media_list_widget.cpp | 1 - .../info/profile/info_profile_actions.cpp | 1 - .../profile/info_profile_inner_widget.cpp | 1 - .../info/profile/info_profile_members.cpp | 5 +- .../SourceFiles/ui/effects/fade_animation.cpp | 52 ++-- .../SourceFiles/ui/effects/fade_animation.h | 4 +- .../ui/effects/numbers_animation.cpp | 10 + .../ui/effects/numbers_animation.h | 6 + .../ui/search_field_controller.cpp | 4 +- Telegram/SourceFiles/ui/twidget.h | 69 +++-- Telegram/SourceFiles/ui/widgets/buttons.cpp | 28 +- Telegram/SourceFiles/ui/widgets/buttons.h | 25 +- .../SourceFiles/ui/widgets/multi_select.cpp | 8 +- Telegram/SourceFiles/ui/wrap/fade_wrap.cpp | 4 +- Telegram/SourceFiles/ui/wrap/fade_wrap.h | 14 +- .../window/themes/window_theme_editor.cpp | 2 +- Telegram/gyp/telegram_sources.txt | 2 - 27 files changed, 341 insertions(+), 502 deletions(-) delete mode 100644 Telegram/SourceFiles/info/info_top_bar_override.cpp delete mode 100644 Telegram/SourceFiles/info/info_top_bar_override.h diff --git a/Telegram/SourceFiles/base/unique_qptr.h b/Telegram/SourceFiles/base/unique_qptr.h index f10a357da..1aeffea7d 100644 --- a/Telegram/SourceFiles/base/unique_qptr.h +++ b/Telegram/SourceFiles/base/unique_qptr.h @@ -26,18 +26,18 @@ template class unique_qptr { public: unique_qptr() = default; - unique_qptr(std::nullptr_t) { + unique_qptr(std::nullptr_t) noexcept { } - explicit unique_qptr(T *pointer) + explicit unique_qptr(T *pointer) noexcept : _object(pointer) { } unique_qptr(const unique_qptr &other) = delete; unique_qptr &operator=(const unique_qptr &other) = delete; - unique_qptr(unique_qptr &&other) + unique_qptr(unique_qptr &&other) noexcept : _object(base::take(other._object)) { } - unique_qptr &operator=(unique_qptr &&other) { + unique_qptr &operator=(unique_qptr &&other) noexcept { if (_object != other._object) { destroy(); _object = base::take(other._object); @@ -48,14 +48,14 @@ public: template < typename U, typename = std::enable_if_t>> - unique_qptr(unique_qptr &&other) + unique_qptr(unique_qptr &&other) noexcept : _object(base::take(other._object)) { } template < typename U, typename = std::enable_if_t>> - unique_qptr &operator=(unique_qptr &&other) { + unique_qptr &operator=(unique_qptr &&other) noexcept { if (_object != other._object) { destroy(); _object = base::take(other._object); @@ -63,49 +63,60 @@ public: return *this; } - unique_qptr &operator=(std::nullptr_t) { + unique_qptr &operator=(std::nullptr_t) noexcept { destroy(); return *this; } - void reset(T *value = nullptr) { + template + explicit unique_qptr(std::in_place_t, Args &&...args) + : _object(new T(std::forward(args)...)) { + } + + template + T *emplace(Args &&...args) { + reset(new T(std::forward(args)...)); + return get(); + } + + void reset(T *value = nullptr) noexcept { if (_object != value) { destroy(); _object = value; } } - T *get() const { + T *get() const noexcept { return static_cast(_object.data()); } - operator T*() const { + operator T*() const noexcept { return get(); } - T *release() { + T *release() noexcept { return static_cast(base::take(_object).data()); } - explicit operator bool() const { + explicit operator bool() const noexcept { return _object != nullptr; } - T *operator->() const { + T *operator->() const noexcept { return get(); } - T &operator*() const { + T &operator*() const noexcept { return *get(); } - void destroy() { - delete base::take(_object).data(); - } - - ~unique_qptr() { + ~unique_qptr() noexcept { destroy(); } private: + void destroy() noexcept { + delete base::take(_object).data(); + } + template friend class unique_qptr; @@ -115,7 +126,7 @@ private: template inline unique_qptr make_unique_q(Args &&...args) { - return unique_qptr(new T(std::forward(args)...)); + return unique_qptr(std::in_place, std::forward(args)...); } } // namespace base diff --git a/Telegram/SourceFiles/boxes/stickers_box.cpp b/Telegram/SourceFiles/boxes/stickers_box.cpp index 0e3e5879e..109b1dc37 100644 --- a/Telegram/SourceFiles/boxes/stickers_box.cpp +++ b/Telegram/SourceFiles/boxes/stickers_box.cpp @@ -1350,7 +1350,7 @@ void StickersBox::Inner::rebuildMegagroupSet() { if (!_megagroupSelectedRemove) { _megagroupSelectedRemove.create(this, st::groupStickersRemove); - _megagroupSelectedRemove->showFast(); + _megagroupSelectedRemove->show(anim::type::instant); _megagroupSelectedRemove->setClickedCallback([this] { setMegagroupSelectedSet(MTP_inputStickerSetEmpty()); }); diff --git a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp index d52364b05..4a7509c8a 100644 --- a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp @@ -85,7 +85,9 @@ GifsListWidget::Footer::Footer(not_null parent) : InnerFooter(p } }); connect(_field, &Ui::InputField::changed, this, [this] { - _cancel->toggleAnimated(!_field->getLastText().isEmpty()); + _cancel->toggle( + !_field->getLastText().isEmpty(), + anim::type::normal); _pan->searchForGifs(_field->getLastText()); }); _cancel->setClickedCallback([this] { diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp index 0f90da51c..73953541c 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp @@ -267,7 +267,7 @@ void DialogsWidget::showAnimated(Window::SlideDirection direction, const Window: _mainMenuToggle->hide(); if (_forwardCancel) _forwardCancel->hide(); _filter->hide(); - _cancelSearch->hide(); + _cancelSearch->hide(anim::type::instant); _jumpToDate->hide(anim::type::instant); _chooseFromUser->hide(anim::type::instant); _lockUnlock->hide(); @@ -827,10 +827,8 @@ void DialogsWidget::onFilterUpdate(bool force) { _inner->onFilterUpdate(filterText, force); if (filterText.isEmpty()) { clearSearchCache(); - _cancelSearch->hideAnimated(); - } else { - _cancelSearch->showAnimated(); } + _cancelSearch->toggle(!filterText.isEmpty(), anim::type::normal); updateJumpToDateVisibility(); if (filterText.size() < MinUsernameLength) { diff --git a/Telegram/SourceFiles/history/history_admin_log_section.cpp b/Telegram/SourceFiles/history/history_admin_log_section.cpp index 5bd78e2ab..6c8132497 100644 --- a/Telegram/SourceFiles/history/history_admin_log_section.cpp +++ b/Telegram/SourceFiles/history/history_admin_log_section.cpp @@ -128,7 +128,7 @@ FixedBar::FixedBar( connect(_field, &Ui::FlatInput::submitted, this, [this] { applySearch(); }); _searchTimer.setCallback([this] { applySearch(); }); - _cancel->hideFast(); + _cancel->hide(anim::type::instant); } void FixedBar::applyFilter(const FilterValue &value) { @@ -148,7 +148,7 @@ void FixedBar::showSearch() { void FixedBar::toggleSearch() { _searchShown = !_searchShown; - _cancel->toggleAnimated(_searchShown); + _cancel->toggle(_searchShown, anim::type::normal); _searchShownAnimation.start([this] { searchAnimationCallback(); }, _searchShown ? 0. : 1., _searchShown ? 1. : 0., st::historyAdminLogSearchSlideDuration); _search->setDisabled(_searchShown); if (_searchShown) { @@ -227,7 +227,7 @@ void FixedBar::setAnimatingMode(bool enabled) { setAttribute(Qt::WA_OpaquePaintEvent); showChildren(); _field->hide(); - _cancel->hide(); + _cancel->setVisible(false); } show(); } diff --git a/Telegram/SourceFiles/info/info.style b/Telegram/SourceFiles/info/info.style index f8136ea6a..b276e7f7b 100644 --- a/Telegram/SourceFiles/info/info.style +++ b/Telegram/SourceFiles/info/info.style @@ -190,6 +190,8 @@ infoTopBar: InfoTopBar { highlightBg: windowBgOver; highlightDuration: 240; } +infoTopBarScale: 0.7; +infoTopBarDuration: 150; infoLayerTopMinimal: 20px; infoLayerTopMaximal: 40px; diff --git a/Telegram/SourceFiles/info/info_top_bar.cpp b/Telegram/SourceFiles/info/info_top_bar.cpp index b5c6217d9..026c7213c 100644 --- a/Telegram/SourceFiles/info/info_top_bar.cpp +++ b/Telegram/SourceFiles/info/info_top_bar.cpp @@ -50,18 +50,50 @@ TopBar::TopBar( , _selectedItems(Section::MediaType::kCount) { setAttribute(Qt::WA_OpaquePaintEvent); setSelectedItems(std::move(selectedItems)); - finishSelectionAnimations(); + updateControlsVisibility(anim::type::instant); +} + +template +void TopBar::registerUpdateControlCallback( + QObject *guard, + Callback &&callback) { + _updateControlCallbacks[guard] =[ + object = weak(guard), + callback = std::forward(callback) + ](anim::type animated) { + if (!object) { + return false; + } + callback(animated); + return true; + }; +} + +template +void TopBar::registerToggleControlCallback( + Widget *widget, + IsVisible &&callback) { + registerUpdateControlCallback(widget, [ + widget, + isVisible = std::forward(callback) + ](anim::type animated) { + widget->toggle(isVisible(), animated); + }); } void TopBar::setTitle(rpl::producer &&title) { if (_title) { delete _title; } - _title = Ui::CreateChild>( + _title = Ui::CreateChild>( this, - object_ptr(this, std::move(title), _st.title)); + object_ptr(this, std::move(title), _st.title), + st::infoTopBarScale); + _title->setDuration(st::infoTopBarDuration); _title->toggle(!selectionMode(), anim::type::instant); - _defaultControls.push_back(_title.data()); + registerToggleControlCallback(_title.data(), [=] { + return !selectionMode() && !searchMode(); + }); if (_back) { _title->setAttribute(Qt::WA_TransparentForMouseEvents); @@ -73,13 +105,17 @@ void TopBar::enableBackButton() { if (_back) { return; } - _back = Ui::CreateChild>( + _back = Ui::CreateChild>( this, - object_ptr(this, _st.back)); + object_ptr(this, _st.back), + st::infoTopBarScale); + _back->setDuration(st::infoTopBarDuration); _back->toggle(!selectionMode(), anim::type::instant); _back->entity()->clicks() | rpl::start_to_stream(_backClicks, _back->lifetime()); - _defaultControls.push_back(_back.data()); + registerToggleControlCallback(_back.data(), [=] { + return !selectionMode(); + }); if (_title) { _title->setAttribute(Qt::WA_TransparentForMouseEvents); @@ -95,14 +131,24 @@ void TopBar::createSearchView( std::move(shown)); } -void TopBar::pushButton(base::unique_qptr button) { - auto weak = button.get(); - _buttons.push_back(std::move(button)); - weak->setParent(this); +Ui::FadeWrap *TopBar::pushButton( + base::unique_qptr button) { + auto wrapped = base::make_unique_q>( + this, + object_ptr::fromRaw(button.release()), + st::infoTopBarScale); + auto weak = wrapped.get(); + _buttons.push_back(std::move(wrapped)); + weak->setDuration(st::infoTopBarDuration); + registerToggleControlCallback(weak, [=] { + return !selectionMode() + && !_searchModeEnabled; + }); weak->widthValue() | rpl::start_with_next([this] { updateControlsGeometry(width()); }, lifetime()); + return weak; } void TopBar::setSearchField( @@ -122,59 +168,75 @@ void TopBar::createSearchView( this, _st.searchRow.height); auto wrap = _searchView.get(); + registerUpdateControlCallback(wrap, [=](anim::type) { + wrap->setVisible(!selectionMode() && _searchModeAvailable); + }); - field->setParent(wrap); - - auto search = addButton( - base::make_unique_q>>( - this, - object_ptr>( - this, - object_ptr(this, _st.search)))); - _defaultControls.push_back(search); - auto cancel = Ui::CreateChild>( + auto fieldWrap = Ui::CreateChild>( wrap, - object_ptr(wrap, _st.searchRow.fieldCancel)); - _defaultControls.push_back(cancel); + object_ptr::fromRaw(field), + st::infoTopBarScale); + fieldWrap->setDuration(st::infoTopBarDuration); - auto toggleSearchMode = [=](bool enabled, anim::type animated) { - if (!enabled) { + auto focusLifetime = field->lifetime().make_state(); + registerUpdateControlCallback(fieldWrap, [=](anim::type animated) { + auto fieldShown = !selectionMode() && searchMode(); + if (!fieldShown && field->hasFocus()) { setFocus(); } - if (_title) { - _title->entity()->setVisible(!enabled); + fieldWrap->toggle(fieldShown, animated); + if (fieldShown) { + *focusLifetime = field->shownValue() + | rpl::filter([](bool shown) { return shown; }) + | rpl::take(1) + | rpl::start_with_next([=] { + field->setFocus(); + }); + } else { + focusLifetime->destroy(); } - field->setVisible(enabled); - cancel->entity()->toggleAnimated(enabled); - if (animated == anim::type::instant) { - cancel->entity()->finishAnimations(); - } - search->wrapped()->toggle(!enabled, animated); - if (enabled) { - field->setFocus(); - } - }; + }); + + auto button = base::make_unique_q(this, _st.search); + auto search = button.get(); + search->addClickHandler([=] { + _searchModeEnabled = true; + updateControlsVisibility(anim::type::normal); + }); + auto searchWrap = pushButton(std::move(button)); + registerToggleControlCallback(searchWrap, [=] { + return !selectionMode() + && _searchModeAvailable + && !_searchModeEnabled; + }); + + auto cancel = Ui::CreateChild( + wrap, + _st.searchRow.fieldCancel); + registerToggleControlCallback(cancel, [=] { + return !selectionMode() && searchMode(); + }); auto cancelSearch = [=] { if (!field->getLastText().isEmpty()) { field->setText(QString()); } else { - toggleSearchMode(false, anim::type::normal); + _searchModeEnabled = false; + updateControlsVisibility(anim::type::normal); } }; - cancel->entity()->addClickHandler(cancelSearch); + cancel->addClickHandler(cancelSearch); field->connect(field, &Ui::InputField::cancelled, cancelSearch); wrap->widthValue() | rpl::start_with_next([=](int newWidth) { auto availableWidth = newWidth - _st.searchRow.fieldCancelSkip; - field->setGeometryToLeft( + fieldWrap->resizeToWidth(availableWidth); + fieldWrap->moveToLeft( _st.searchRow.padding.left(), - _st.searchRow.padding.top(), - availableWidth, - field->height()); + _st.searchRow.padding.top()); cancel->moveToRight(0, 0); }, wrap->lifetime()); @@ -191,10 +253,6 @@ void TopBar::createSearchView( newWidth); }, wrap->lifetime()); - search->entity()->addClickHandler([=] { - toggleSearchMode(true, anim::type::normal); - }); - field->alive() | rpl::start_with_done([=] { field->setParent(nullptr); @@ -202,18 +260,14 @@ void TopBar::createSearchView( setSearchField(nullptr, rpl::never()); }, _searchView->lifetime()); - toggleSearchMode( - !field->getLastText().isEmpty(), - anim::type::instant); + _searchModeEnabled = !field->getLastText().isEmpty(); + updateControlsVisibility(anim::type::instant); std::move(shown) | rpl::start_with_next([=](bool visible) { - if (!field->getLastText().isEmpty()) { - return; - } - toggleSearchMode(false, anim::type::instant); - wrap->setVisible(visible); - search->wrapped()->toggle(visible, anim::type::instant); + auto alreadyInSearch = !field->getLastText().isEmpty(); + _searchModeAvailable = visible || alreadyInSearch; + updateControlsVisibility(anim::type::instant); }, wrap->lifetime()); } @@ -228,17 +282,6 @@ int TopBar::resizeGetHeight(int newWidth) { return _st.height; } -void TopBar::finishSelectionAnimations() { - ranges::for_each(ranges::view::concat( - _defaultControls, - _selectionControls - ), [](auto &&control) { - if (auto pointer = control.data()) { - pointer->finishAnimating(); - } - }); -} - void TopBar::updateControlsGeometry(int newWidth) { updateDefaultControlsGeometry(newWidth); updateSelectionControlsGeometry(newWidth); @@ -286,7 +329,7 @@ void TopBar::updateSelectionControlsGeometry(int newWidth) { const auto top = 0; const auto availableWidth = newWidth - left - right; - _selectionText->resizeToWidth(availableWidth); + _selectionText->resizeToNaturalWidth(availableWidth); _selectionText->moveToLeft( left, top, @@ -319,16 +362,31 @@ void TopBar::startHighlightAnimation() { _st.highlightDuration); } +void TopBar::updateControlsVisibility(anim::type animated) { + for (auto i = _updateControlCallbacks.begin(); i != _updateControlCallbacks.end();) { + auto &&[widget, callback] = *i; + if (!callback(animated)) { + i = _updateControlCallbacks.erase(i); + } else { + ++i; + } + } +} + void TopBar::setSelectedItems(SelectedItems &&items) { + auto wasSelectionMode = selectionMode(); _selectedItems = std::move(items); if (selectionMode()) { if (_selectionText) { updateSelectionState(); + if (!wasSelectionMode) { + _selectionText->entity()->finishAnimating(); + } } else { createSelectionControls(); } } - toggleSelectionControls(); + updateControlsVisibility(anim::type::normal); } SelectedItems TopBar::takeSelectedItems() { @@ -352,33 +410,43 @@ void TopBar::updateSelectionState() { void TopBar::createSelectionControls() { auto wrap = [&](auto created) { - _selectionControls.push_back(created); + registerToggleControlCallback( + created, + [this] { return selectionMode(); }); created->toggle(false, anim::type::instant); return created; }; _canDelete = computeCanDelete(); - _cancelSelection = wrap(Ui::CreateChild>( + _cancelSelection = wrap(Ui::CreateChild>( this, - object_ptr(this, _st.mediaCancel))); + object_ptr(this, _st.mediaCancel), + st::infoTopBarScale)); + _cancelSelection->setDuration(st::infoTopBarDuration); _cancelSelection->entity()->clicks() | rpl::start_to_stream( _cancelSelectionClicks, _cancelSelection->lifetime()); - _selectionText = wrap(Ui::CreateChild>( + _selectionText = wrap(Ui::CreateChild>( this, object_ptr( this, _st.title, _st.titlePosition.y(), - generateSelectedText()))); + generateSelectedText()), + st::infoTopBarScale)); + _selectionText->setDuration(st::infoTopBarDuration); _selectionText->entity()->resize(0, _st.height); - _forward = wrap(Ui::CreateChild>( + _forward = wrap(Ui::CreateChild>( this, - object_ptr(this, _st.mediaForward))); + object_ptr(this, _st.mediaForward), + st::infoTopBarScale)); + _forward->setDuration(st::infoTopBarDuration); _forward->entity()->addClickHandler([this] { performForward(); }); - _delete = wrap(Ui::CreateChild>( + _delete = wrap(Ui::CreateChild>( this, - object_ptr(this, _st.mediaDelete))); + object_ptr(this, _st.mediaDelete), + st::infoTopBarScale)); + _delete->setDuration(st::infoTopBarDuration); _delete->entity()->addClickHandler([this] { performDelete(); }); _delete->entity()->setVisible(_canDelete); @@ -392,23 +460,6 @@ bool TopBar::computeCanDelete() const { ) == _selectedItems.list.end(); } -void TopBar::toggleSelectionControls() { - auto toggle = [](bool shown) { - return [=](auto &&control) { - if (auto pointer = control.data()) { - pointer->toggle(shown, anim::type::normal); - } - }; - }; - auto shown = selectionMode(); - ranges::for_each(_defaultControls, toggle(!shown)); - ranges::for_each(_selectionControls, toggle(shown)); - - if (!shown) { - clearSelectionControls(); - } -} - Ui::StringWithNumbers TopBar::generateSelectedText() const { using Data = Ui::StringWithNumbers; using Type = Storage::SharedMediaType; @@ -422,7 +473,7 @@ Ui::StringWithNumbers TopBar::generateSelectedText() const { case Type::VoiceFile: return lng_media_selected_audio__generic; // case Type::RoundFile: return lng_media_selected_round__generic; } - Unexpected("Type in TopBarOverride::generateText()"); + Unexpected("Type in TopBar::generateSelectedText()"); }(); return phrase(lt_count, _selectedItems.list.size()); } @@ -431,27 +482,8 @@ bool TopBar::selectionMode() const { return !_selectedItems.list.empty(); } -void TopBar::clearSelectionControls() { - for (auto &&control : _selectionControls) { - if (auto pointer = control.data()) { - pointer->shownValue() - | rpl::filter([](bool shown) { return !shown; }) - | rpl::start_with_next([control] { - if (auto pointer = control.data()) { - InvokeQueued(pointer, [pointer] { delete pointer; }); - } - }, pointer->lifetime()); - } - } - - auto isStale = [](auto &&control) { return !control; }; - _defaultControls |= ranges::action::remove_if(isStale); - _selectionControls |= ranges::action::remove_if(isStale); - - _cancelSelection = nullptr; - _selectionText = nullptr; - _forward = nullptr; - _delete = nullptr; +bool TopBar::searchMode() const { + return _searchModeAvailable && _searchModeEnabled; } SelectedItemSet TopBar::collectItems() const { diff --git a/Telegram/SourceFiles/info/info_top_bar.h b/Telegram/SourceFiles/info/info_top_bar.h index 9777ce0aa..002e0ef63 100644 --- a/Telegram/SourceFiles/info/info_top_bar.h +++ b/Telegram/SourceFiles/info/info_top_bar.h @@ -75,7 +75,6 @@ public: SelectedItems takeSelectedItems(); rpl::producer<> cancelSelectionRequests() const; - void finishSelectionAnimations(); protected: int resizeGetHeight(int newWidth) override; @@ -85,17 +84,18 @@ private: void updateControlsGeometry(int newWidth); void updateDefaultControlsGeometry(int newWidth); void updateSelectionControlsGeometry(int newWidth); - void pushButton(base::unique_qptr button); + Ui::FadeWrap *pushButton(base::unique_qptr button); void removeButton(not_null button); void startHighlightAnimation(); + void updateControlsVisibility(anim::type animated); bool selectionMode() const; + bool searchMode() const; Ui::StringWithNumbers generateSelectedText() const; [[nodiscard]] bool computeCanDelete() const; [[nodiscard]] SelectedItemSet collectSelectedItems() const; void updateSelectionState(); void createSelectionControls(); - void toggleSelectionControls(); void clearSelectionControls(); SelectedItemSet collectItems() const; @@ -109,6 +109,12 @@ private: not_null field, rpl::producer &&shown); + template + void registerUpdateControlCallback(QObject *guard, Callback &&callback); + + template + void registerToggleControlCallback(Widget *widget, IsVisible &&callback); + const style::InfoTopBar &_st; Animation _a_highlight; bool _highlight = false; @@ -116,6 +122,8 @@ private: std::vector> _buttons; QPointer> _title; + bool _searchModeEnabled = false; + bool _searchModeAvailable = false; base::unique_qptr _searchView; rpl::event_stream<> _backClicks; @@ -128,9 +136,8 @@ private: QPointer> _delete; rpl::event_stream<> _cancelSelectionClicks; - using FadingControl = QPointer>; - std::vector _defaultControls; - std::vector _selectionControls; + using UpdateCallback = base::lambda; + std::map _updateControlCallbacks; }; diff --git a/Telegram/SourceFiles/info/info_top_bar_override.cpp b/Telegram/SourceFiles/info/info_top_bar_override.cpp deleted file mode 100644 index dc79f1a64..000000000 --- a/Telegram/SourceFiles/info/info_top_bar_override.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop version of Telegram messaging app, see https://telegram.org - -Telegram Desktop is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -It is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -In addition, as a special exception, the copyright holders give permission -to link the code of portions of this program with the OpenSSL library. - -Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE -Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org -*/ -#include "info/info_top_bar_override.h" - -#include -#include "styles/style_info.h" -#include "lang/lang_keys.h" -#include "info/info_wrap_widget.h" -#include "storage/storage_shared_media.h" -#include "ui/effects/numbers_animation.h" -#include "ui/widgets/buttons.h" -#include "ui/widgets/shadow.h" -#include "ui/wrap/fade_wrap.h" -#include "mainwidget.h" -#include "boxes/confirm_box.h" -#include "boxes/peer_list_controllers.h" - -namespace Info { - -TopBarOverride::TopBarOverride( - QWidget *parent, - const style::InfoTopBar &st, - SelectedItems &&items) -: RpWidget(parent) -, _st(st) -, _items(std::move(items)) -, _canDelete(computeCanDelete()) -, _cancel(this, _st.mediaCancel) -, _text(this, _st.title, _st.titlePosition.y(), generateText()) -, _forward(this, _st.mediaForward) -, _delete(this, _st.mediaDelete) { - setAttribute(Qt::WA_OpaquePaintEvent); - - updateControlsVisibility(); - - _forward->addClickHandler([this] { performForward(); }); - _delete->addClickHandler([this] { performDelete(); }); -} - -Ui::StringWithNumbers TopBarOverride::generateText() const { - using Data = Ui::StringWithNumbers; - using Type = Storage::SharedMediaType; - auto phrase = [&] { - switch (_items.type) { - case Type::Photo: return lng_media_selected_photo__generic; - case Type::Video: return lng_media_selected_video__generic; - case Type::File: return lng_media_selected_file__generic; - case Type::MusicFile: return lng_media_selected_song__generic; - case Type::Link: return lng_media_selected_link__generic; - case Type::VoiceFile: return lng_media_selected_audio__generic; -// case Type::RoundFile: return lng_media_selected_round__generic; - } - Unexpected("Type in TopBarOverride::generateText()"); - }(); - return phrase(lt_count, _items.list.size()); -} - -bool TopBarOverride::computeCanDelete() const { - return ranges::find_if(_items.list, [](const SelectedItem &item) { - return !item.canDelete; - }) == _items.list.end(); -} - -void TopBarOverride::setItems(SelectedItems &&items) { - _items = std::move(items); - _canDelete = computeCanDelete(); - - _text->setValue(generateText()); - updateControlsVisibility(); - updateControlsGeometry(width()); -} - -SelectedItems TopBarOverride::takeItems() { - _canDelete = false; - return std::move(_items); -} - -rpl::producer<> TopBarOverride::cancelRequests() const { - return rpl::merge( - _cancel->clicks(), - _correctionCancelRequests.events()); -} - -int TopBarOverride::resizeGetHeight(int newWidth) { - updateControlsGeometry(newWidth); - return _st.height; -} - -void TopBarOverride::updateControlsGeometry(int newWidth) { - auto right = _st.mediaActionsSkip; - if (_canDelete) { - _delete->moveToRight(right, 0, newWidth); - right += _delete->width(); - } - _forward->moveToRight(right, 0, newWidth); - right += _forward->width(); - - auto left = 0; - _cancel->moveToLeft(left, 0); - left += _cancel->width(); - - const auto availableWidth = newWidth - left - right; - _text->setGeometryToLeft(left, 0, availableWidth, _st.height, newWidth); -} - -void TopBarOverride::updateControlsVisibility() { - _delete->setVisible(_canDelete); -} - -void TopBarOverride::paintEvent(QPaintEvent *e) { - Painter p(this); - p.fillRect(e->rect(), _st.bg); -} - -SelectedItemSet TopBarOverride::collectItems() const { - auto result = SelectedItemSet(); - for (auto value : _items.list) { - if (auto item = App::histItemById(value.msgId)) { - result.insert(result.size(), item); - } - } - return result; -} - -void TopBarOverride::performForward() { - auto items = collectItems(); - if (items.empty()) { - _correctionCancelRequests.fire({}); - return; - } - auto callback = [items = std::move(items), that = weak(this)]( - not_null peer) { - App::main()->setForwardDraft(peer->id, items); - if (that) { - that->_correctionCancelRequests.fire({}); - } - }; - Ui::show(Box( - std::make_unique(std::move(callback)), - [](not_null box) { - box->addButton(langFactory(lng_cancel), [box] { - box->closeBox(); - }); - })); -} - -void TopBarOverride::performDelete() { - auto items = collectItems(); - if (items.empty()) { - _correctionCancelRequests.fire({}); - } else { - Ui::show(Box(items)); - } -} - -} // namespace Info diff --git a/Telegram/SourceFiles/info/info_top_bar_override.h b/Telegram/SourceFiles/info/info_top_bar_override.h deleted file mode 100644 index 65b960d4a..000000000 --- a/Telegram/SourceFiles/info/info_top_bar_override.h +++ /dev/null @@ -1,77 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop version of Telegram messaging app, see https://telegram.org - -Telegram Desktop is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -It is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -In addition, as a special exception, the copyright holders give permission -to link the code of portions of this program with the OpenSSL library. - -Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE -Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org -*/ -#pragma once - -#include "ui/rp_widget.h" -#include "info/info_wrap_widget.h" -#include "boxes/peer_list_controllers.h" - -namespace style { -struct InfoTopBar; -} // namespace style - -namespace Ui { -class IconButton; -class LabelWithNumbers; -struct StringWithNumbers; -} // namespace Ui - -namespace Info { - -class TopBarOverride : public Ui::RpWidget { -public: - TopBarOverride( - QWidget *parent, - const style::InfoTopBar &st, - SelectedItems &&items); - - void setItems(SelectedItems &&items); - SelectedItems takeItems(); - - rpl::producer<> cancelRequests() const; - -protected: - int resizeGetHeight(int newWidth) override; - void paintEvent(QPaintEvent *e) override; - -private: - void updateControlsVisibility(); - void updateControlsGeometry(int newWidth); - Ui::StringWithNumbers generateText() const; - [[nodiscard]] bool computeCanDelete() const; - [[nodiscard]] SelectedItemSet collectItems() const; - - void performForward(); - void performDelete(); - - const style::InfoTopBar &_st; - SelectedItems _items; - bool _canDelete = false; - object_ptr _cancel; - object_ptr _text; - object_ptr _forward; - object_ptr _delete; - rpl::event_stream<> _correctionCancelRequests; - -}; - - -} // namespace Info diff --git a/Telegram/SourceFiles/info/media/info_media_list_widget.cpp b/Telegram/SourceFiles/info/media/info_media_list_widget.cpp index 554ecaa2a..e72455d73 100644 --- a/Telegram/SourceFiles/info/media/info_media_list_widget.cpp +++ b/Telegram/SourceFiles/info/media/info_media_list_widget.cpp @@ -36,7 +36,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "styles/style_info.h" #include "boxes/peer_list_controllers.h" #include "boxes/confirm_box.h" -#include "info/info_top_bar_override.h" #include "core/file_utilities.h" namespace Layout = Overview::Layout; diff --git a/Telegram/SourceFiles/info/profile/info_profile_actions.cpp b/Telegram/SourceFiles/info/profile/info_profile_actions.cpp index 10616ee75..7372b2113 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_actions.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_actions.cpp @@ -38,7 +38,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "lang/lang_keys.h" #include "info/info_controller.h" #include "info/info_memento.h" -#include "info/info_top_bar_override.h" #include "info/profile/info_profile_icon.h" #include "info/profile/info_profile_values.h" #include "info/profile/info_profile_button.h" diff --git a/Telegram/SourceFiles/info/profile/info_profile_inner_widget.cpp b/Telegram/SourceFiles/info/profile/info_profile_inner_widget.cpp index 5a9212c79..a30005744 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_inner_widget.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_inner_widget.cpp @@ -25,7 +25,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include #include "info/info_memento.h" #include "info/info_controller.h" -#include "info/info_top_bar_override.h" #include "info/profile/info_profile_button.h" #include "info/profile/info_profile_widget.h" #include "info/profile/info_profile_text.h" diff --git a/Telegram/SourceFiles/info/profile/info_profile_members.cpp b/Telegram/SourceFiles/info/profile/info_profile_members.cpp index 7e7eee4dd..39b16a173 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_members.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_members.cpp @@ -187,7 +187,7 @@ void Members::setupButtons() { }); //_searchField->hide(); - //_cancelSearch->hideFast(); + //_cancelSearch->setVisible(false); auto addMemberShown = CanAddMemberValue(_peer) | rpl::start_spawning(lifetime()); @@ -344,15 +344,14 @@ void Members::addMember() { // //void Members::toggleSearch(anim::type animated) { // _searchShown = !_searchShown; +// _cancelSearch->toggle(_searchShown, animated); // if (animated == anim::type::normal) { -// _cancelSearch->toggleAnimated(_searchShown); // _searchShownAnimation.start( // [this] { searchAnimationCallback(); }, // _searchShown ? 0. : 1., // _searchShown ? 1. : 0., // st::slideWrapDuration); // } else { -// _cancelSearch->toggleFast(_searchShown); // _searchShownAnimation.finish(); // searchAnimationCallback(); // } diff --git a/Telegram/SourceFiles/ui/effects/fade_animation.cpp b/Telegram/SourceFiles/ui/effects/fade_animation.cpp index 8a308d95b..987f6e0d9 100644 --- a/Telegram/SourceFiles/ui/effects/fade_animation.cpp +++ b/Telegram/SourceFiles/ui/effects/fade_animation.cpp @@ -27,9 +27,9 @@ constexpr int kWideScale = 5; } // namespace -FadeAnimation::FadeAnimation(TWidget *widget, bool scaled) +FadeAnimation::FadeAnimation(TWidget *widget, float64 scale) : _widget(widget) -, _scaled(scaled) { +, _scale(scale) { } bool FadeAnimation::paint(Painter &p) { @@ -37,13 +37,28 @@ bool FadeAnimation::paint(Painter &p) { auto opacity = _animation.current(getms(), _visible ? 1. : 0.); p.setOpacity(opacity); - if (_scaled) { + if (_scale < 1.) { PainterHighQualityEnabler hq(p); - auto targetRect = QRect((1 - kWideScale) / 2 * _size.width(), (1 - kWideScale) / 2 * _size.height(), kWideScale * _size.width(), kWideScale * _size.height()); - auto scale = opacity; - auto shownWidth = anim::interpolate((1 - kWideScale) / 2 * _size.width(), 0, scale); - auto shownHeight = anim::interpolate((1 - kWideScale) / 2 * _size.height(), 0, scale); - p.drawPixmap(targetRect.marginsAdded(QMargins(shownWidth, shownHeight, shownWidth, shownHeight)), _cache); + auto targetRect = QRect( + (1 - kWideScale) / 2 * _size.width(), + (1 - kWideScale) / 2 * _size.height(), + kWideScale * _size.width(), + kWideScale * _size.height()); + auto scale = opacity + (1. - opacity) * _scale; + auto shownWidth = anim::interpolate( + (1 - kWideScale) / 2 * _size.width(), + 0, + scale); + auto shownHeight = anim::interpolate( + (1 - kWideScale) / 2 * _size.height(), + 0, + scale); + auto margins = QMargins( + shownWidth, + shownHeight, + shownWidth, + shownHeight); + p.drawPixmap(targetRect.marginsAdded(margins), _cache); } else { p.drawPixmap(0, 0, _cache); } @@ -70,18 +85,17 @@ QPixmap FadeAnimation::grabContent() { return App::pixmapFromImageInPlace(std::move(image)); } auto widgetContent = myGrab(_widget); - if (!_scaled) { - return widgetContent; + if (_scale < 1.) { + auto result = QImage(kWideScale * _size * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied); + result.setDevicePixelRatio(cRetinaFactor()); + result.fill(Qt::transparent); + { + Painter p(&result); + p.drawPixmap((kWideScale - 1) / 2 * _size.width(), (kWideScale - 1) / 2 * _size.height(), widgetContent); + } + return App::pixmapFromImageInPlace(std::move(result)); } - - auto result = QImage(kWideScale * _size * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied); - result.setDevicePixelRatio(cRetinaFactor()); - result.fill(Qt::transparent); - { - Painter p(&result); - p.drawPixmap((kWideScale - 1) / 2 * _size.width(), (kWideScale - 1) / 2 * _size.height(), widgetContent); - } - return App::pixmapFromImageInPlace(std::move(result)); + return widgetContent; } void FadeAnimation::setFinishedCallback(FinishedCallback &&callback) { diff --git a/Telegram/SourceFiles/ui/effects/fade_animation.h b/Telegram/SourceFiles/ui/effects/fade_animation.h index 02ab35f1f..62e4494a2 100644 --- a/Telegram/SourceFiles/ui/effects/fade_animation.h +++ b/Telegram/SourceFiles/ui/effects/fade_animation.h @@ -27,7 +27,7 @@ namespace Ui { class FadeAnimation { public: - FadeAnimation(TWidget *widget, bool scaled = false); + FadeAnimation(TWidget *widget, float64 scale = 1.); bool paint(Painter &p); void refreshCache(); @@ -63,7 +63,7 @@ private: QPixmap grabContent(); TWidget *_widget = nullptr; - bool _scaled = false; + float64 _scale = 1.; Animation _animation; QSize _size; diff --git a/Telegram/SourceFiles/ui/effects/numbers_animation.cpp b/Telegram/SourceFiles/ui/effects/numbers_animation.cpp index e25084bf0..f71326989 100644 --- a/Telegram/SourceFiles/ui/effects/numbers_animation.cpp +++ b/Telegram/SourceFiles/ui/effects/numbers_animation.cpp @@ -105,6 +105,10 @@ int NumbersAnimation::countWidth() const { anim::easeOutCirc(1., _a_ready.current(1.))); } +int NumbersAnimation::maxWidth() const { + return std::max(_fromWidth, _toWidth); +} + void NumbersAnimation::stepAnimation(TimeMs ms) { _a_ready.step(ms); } @@ -212,6 +216,12 @@ void LabelWithNumbers::setValue(const StringWithNumbers &value) { _afterWidth = _st.style.font->width(_after); } +void LabelWithNumbers::finishAnimating() { + _beforeWidthAnimation.finish(); + _numbers.finishAnimating(); + update(); +} + void LabelWithNumbers::paintEvent(QPaintEvent *e) { Painter p(this); diff --git a/Telegram/SourceFiles/ui/effects/numbers_animation.h b/Telegram/SourceFiles/ui/effects/numbers_animation.h index 225ab99a9..34b4f7c3a 100644 --- a/Telegram/SourceFiles/ui/effects/numbers_animation.h +++ b/Telegram/SourceFiles/ui/effects/numbers_animation.h @@ -43,6 +43,7 @@ public: void paint(Painter &p, int x, int y, int outerWidth); int countWidth() const; + int maxWidth() const; private: struct Digit { @@ -90,6 +91,11 @@ public: const StringWithNumbers &value); void setValue(const StringWithNumbers &value); + void finishAnimating(); + + int naturalWidth() const override { + return _beforeWidth + _numbers.maxWidth() + _afterWidth; + } protected: void paintEvent(QPaintEvent *e) override; diff --git a/Telegram/SourceFiles/ui/search_field_controller.cpp b/Telegram/SourceFiles/ui/search_field_controller.cpp index 931dc5979..5c9cc37f4 100644 --- a/Telegram/SourceFiles/ui/search_field_controller.cpp +++ b/Telegram/SourceFiles/ui/search_field_controller.cpp @@ -58,9 +58,9 @@ base::unique_qptr SearchFieldController::createRowView( return !value.isEmpty(); }) | rpl::start_with_next([cancel](bool shown) { - cancel->toggleAnimated(shown); + cancel->toggle(shown, anim::type::normal); }, cancel->lifetime()); - cancel->finishAnimations(); + cancel->finishAnimating(); auto shadow = CreateChild(wrap); shadow->show(); diff --git a/Telegram/SourceFiles/ui/twidget.h b/Telegram/SourceFiles/ui/twidget.h index 1605a0e14..4e64f30c7 100644 --- a/Telegram/SourceFiles/ui/twidget.h +++ b/Telegram/SourceFiles/ui/twidget.h @@ -472,57 +472,70 @@ private: template class object_ptr { public: - object_ptr(std::nullptr_t) { + object_ptr(std::nullptr_t) noexcept { } // No default constructor, but constructors with at least // one argument are simply make functions. template - explicit object_ptr(Parent &&parent, Args&&... args) : _object(new Object(std::forward(parent), std::forward(args)...)) { + explicit object_ptr(Parent &&parent, Args&&... args) + : _object(new Object(std::forward(parent), std::forward(args)...)) { + } + static object_ptr fromRaw(Object *value) noexcept { + object_ptr result = { nullptr }; + result._object = value; + return result; } object_ptr(const object_ptr &other) = delete; object_ptr &operator=(const object_ptr &other) = delete; - object_ptr(object_ptr &&other) : _object(base::take(other._object)) { + object_ptr(object_ptr &&other) noexcept : _object(base::take(other._object)) { } - object_ptr &operator=(object_ptr &&other) { + object_ptr &operator=(object_ptr &&other) noexcept { auto temp = std::move(other); destroy(); std::swap(_object, temp._object); return *this; } - template ::value>> - object_ptr(object_ptr &&other) : _object(base::take(other._object)) { + template < + typename OtherObject, + typename = std::enable_if_t< + std::is_base_of_v>> + object_ptr(object_ptr &&other) noexcept + : _object(base::take(other._object)) { } - template ::value>> - object_ptr &operator=(object_ptr &&other) { + template < + typename OtherObject, + typename = std::enable_if_t< + std::is_base_of_v>> + object_ptr &operator=(object_ptr &&other) noexcept { _object = base::take(other._object); return *this; } - object_ptr &operator=(std::nullptr_t) { + object_ptr &operator=(std::nullptr_t) noexcept { _object = nullptr; return *this; } // So we can pass this pointer to methods like connect(). - Object *data() const { + Object *data() const noexcept { return static_cast(_object.data()); } - operator Object*() const { + operator Object*() const noexcept { return data(); } - explicit operator bool() const { + explicit operator bool() const noexcept { return _object != nullptr; } - Object *operator->() const { + Object *operator->() const noexcept { return data(); } - Object &operator*() const { + Object &operator*() const noexcept { return *data(); } @@ -530,10 +543,12 @@ public: template Object *create(Parent &&parent, Args&&... args) { destroy(); - _object = new Object(std::forward(parent), std::forward(args)...); + _object = new Object( + std::forward(parent), + std::forward(args)...); return data(); } - void destroy() { + void destroy() noexcept { delete base::take(_object); } void destroyDelayed() { @@ -545,7 +560,7 @@ public: } } - ~object_ptr() { + ~object_ptr() noexcept { if (auto pointer = _object) { if (!pointer->parent()) { destroy(); @@ -554,7 +569,8 @@ public: } template - friend object_ptr static_object_cast(object_ptr source); + friend object_ptr static_object_cast( + object_ptr source); private: template @@ -565,14 +581,23 @@ private: }; template -inline object_ptr static_object_cast(object_ptr source) { +inline object_ptr static_object_cast( + object_ptr source) { auto result = object_ptr(nullptr); - result._object = static_cast(base::take(source._object).data()); + result._object = static_cast( + base::take(source._object).data()); return std::move(result); } -void sendSynteticMouseEvent(QWidget *widget, QEvent::Type type, Qt::MouseButton button, const QPoint &globalPoint); +void sendSynteticMouseEvent( + QWidget *widget, + QEvent::Type type, + Qt::MouseButton button, + const QPoint &globalPoint); -inline void sendSynteticMouseEvent(QWidget *widget, QEvent::Type type, Qt::MouseButton button) { +inline void sendSynteticMouseEvent( + QWidget *widget, + QEvent::Type type, + Qt::MouseButton button) { return sendSynteticMouseEvent(widget, type, button, QCursor::pos()); } diff --git a/Telegram/SourceFiles/ui/widgets/buttons.cpp b/Telegram/SourceFiles/ui/widgets/buttons.cpp index 7ef7d8cbf..2a45b6364 100644 --- a/Telegram/SourceFiles/ui/widgets/buttons.cpp +++ b/Telegram/SourceFiles/ui/widgets/buttons.cpp @@ -478,7 +478,7 @@ CrossButton::CrossButton(QWidget *parent, const style::CrossButton &st) : Ripple , _a_loading(animation(this, &CrossButton::step_loading)) { resize(_st.width, _st.height); setCursor(style::cur_pointer); - hide(); + setVisible(false); } void CrossButton::step_loading(TimeMs ms, bool timer) { @@ -490,21 +490,29 @@ void CrossButton::step_loading(TimeMs ms, bool timer) { } } -void CrossButton::toggleAnimated(bool visible) { - if (_shown == visible) { - return; +void CrossButton::toggle(bool visible, anim::type animated) { + if (_shown != visible) { + _shown = visible; + if (animated == anim::type::normal) { + if (isHidden()) { + setVisible(true); + } + _a_show.start( + [this] { animationCallback(); }, + _shown ? 0. : 1., + _shown ? 1. : 0., + _st.duration); + } } - _shown = visible; - if (isHidden()) { - show(); + if (animated == anim::type::instant) { + finishAnimating(); } - _a_show.start([this] { animationCallback(); }, _shown ? 0. : 1., _shown ? 1. : 0., _st.duration); } void CrossButton::animationCallback() { update(); - if (!_shown && !_a_show.animating()) { - hide(); + if (!_a_show.animating()) { + setVisible(_shown); } } diff --git a/Telegram/SourceFiles/ui/widgets/buttons.h b/Telegram/SourceFiles/ui/widgets/buttons.h index a111656bc..5fd0f3bb7 100644 --- a/Telegram/SourceFiles/ui/widgets/buttons.h +++ b/Telegram/SourceFiles/ui/widgets/buttons.h @@ -212,28 +212,19 @@ class CrossButton : public RippleButton { public: CrossButton(QWidget *parent, const style::CrossButton &st); - void showAnimated() { - toggleAnimated(true); + void toggle(bool shown, anim::type animated); + void show(anim::type animated) { + return toggle(true, animated); } - void hideAnimated() { - toggleAnimated(false); + void hide(anim::type animated) { + return toggle(false, animated); } - void toggleAnimated(bool visible); - void showFast() { - toggleFast(true); - } - void hideFast() { - toggleFast(false); - } - void toggleFast(bool visible) { - toggleAnimated(visible); - finishAnimations(); - } - void finishAnimations() { + void finishAnimating() { _a_show.finish(); + animationCallback(); } - bool isShown() const { + bool toggled() const { return _shown; } void setLoadingAnimation(bool enabled); diff --git a/Telegram/SourceFiles/ui/widgets/multi_select.cpp b/Telegram/SourceFiles/ui/widgets/multi_select.cpp index 76ab2dcbf..232a15c29 100644 --- a/Telegram/SourceFiles/ui/widgets/multi_select.cpp +++ b/Telegram/SourceFiles/ui/widgets/multi_select.cpp @@ -383,11 +383,7 @@ MultiSelect::Inner::Inner(QWidget *parent, const style::MultiSelect &st, base::l void MultiSelect::Inner::onQueryChanged() { auto query = getQuery(); - if (query.isEmpty()) { - _cancel->hideAnimated(); - } else { - _cancel->showAnimated(); - } + _cancel->toggle(!query.isEmpty(), anim::type::normal); updateFieldGeometry(); if (_queryChangedCallback) { _queryChangedCallback(query); @@ -422,7 +418,7 @@ void MultiSelect::Inner::setSubmittedCallback(base::lambdaisShown()) { + if (_cancel->toggled()) { fieldFinalWidth -= _st.fieldCancelSkip; } _field->resizeToWidth(fieldFinalWidth); diff --git a/Telegram/SourceFiles/ui/wrap/fade_wrap.cpp b/Telegram/SourceFiles/ui/wrap/fade_wrap.cpp index c100817e0..f8b403ec0 100644 --- a/Telegram/SourceFiles/ui/wrap/fade_wrap.cpp +++ b/Telegram/SourceFiles/ui/wrap/fade_wrap.cpp @@ -27,9 +27,9 @@ namespace Ui { FadeWrap::FadeWrap( QWidget *parent, object_ptr &&child, - bool scaled) + float64 scale) : Parent(parent, std::move(child)) -, _animation(this, scaled) +, _animation(this, scale) , _duration(st::fadeWrapDuration) { if (auto weak = wrapped()) { weak->show(); diff --git a/Telegram/SourceFiles/ui/wrap/fade_wrap.h b/Telegram/SourceFiles/ui/wrap/fade_wrap.h index 596b2cbd5..21f312356 100644 --- a/Telegram/SourceFiles/ui/wrap/fade_wrap.h +++ b/Telegram/SourceFiles/ui/wrap/fade_wrap.h @@ -36,13 +36,10 @@ class FadeWrap : public Wrap { using Parent = Wrap; public: - FadeWrap(QWidget *parent, object_ptr &&child) - : FadeWrap(parent, std::move(child), false) { - } FadeWrap( QWidget *parent, object_ptr &&child, - bool scaled); + float64 scale = 1.); FadeWrap *setDuration(int duration); FadeWrap *toggle(bool shown, anim::type animated); @@ -81,14 +78,11 @@ class FadeWrap : public Wrap> { using Parent = Wrap>; public: - FadeWrap(QWidget *parent, object_ptr &&child) - : Parent(parent, std::move(child)) { - } FadeWrap( QWidget *parent, object_ptr &&child, - bool scaled) - : Parent(parent, std::move(child), scaled) { + float64 scale = 1.) + : Parent(parent, std::move(child), scale) { } FadeWrap *setDuration(int duration) { @@ -123,7 +117,7 @@ class FadeWrapScaled : public FadeWrap { public: FadeWrapScaled(QWidget *parent, object_ptr &&child) - : Parent(parent, std::move(child), true) { + : Parent(parent, std::move(child), 0.) { } }; diff --git a/Telegram/SourceFiles/window/themes/window_theme_editor.cpp b/Telegram/SourceFiles/window/themes/window_theme_editor.cpp index 60c1c89ae..060e22d1a 100644 --- a/Telegram/SourceFiles/window/themes/window_theme_editor.cpp +++ b/Telegram/SourceFiles/window/themes/window_theme_editor.cpp @@ -727,7 +727,7 @@ Editor::Editor(QWidget*, const QString &path) _scroll->scrollToY(top, bottom); }); _close->setClickedCallback([this] { closeEditor(); }); - _close->showFast(); + _close->show(anim::type::instant); _select->resizeToWidth(st::windowMinWidth); _select->setQueryChangedCallback([this](const QString &query) { _inner->filterRows(query); _scroll->scrollToY(0); }); diff --git a/Telegram/gyp/telegram_sources.txt b/Telegram/gyp/telegram_sources.txt index eaad43edb..6da517c28 100644 --- a/Telegram/gyp/telegram_sources.txt +++ b/Telegram/gyp/telegram_sources.txt @@ -234,8 +234,6 @@ <(src_loc)/info/info_section_widget.h <(src_loc)/info/info_top_bar.cpp <(src_loc)/info/info_top_bar.h -<(src_loc)/info/info_top_bar_override.cpp -<(src_loc)/info/info_top_bar_override.h <(src_loc)/info/info_wrap_widget.cpp <(src_loc)/info/info_wrap_widget.h <(src_loc)/info/common_groups/info_common_groups_inner_widget.cpp