diff --git a/Telegram/SourceFiles/editor/editor.style b/Telegram/SourceFiles/editor/editor.style index 52b79fa5a..dd2abf492 100644 --- a/Telegram/SourceFiles/editor/editor.style +++ b/Telegram/SourceFiles/editor/editor.style @@ -17,6 +17,8 @@ photoEditorControlsHeight: 146px; photoEditorControlsBottomSkip: 20px; photoEditorControlsCenterSkip: 6px; +photoEditorBarAnimationDuration: 200; + photoEditorButtonIconFg: mediaviewPipControlsFg; photoEditorButtonIconFgOver: mediaviewPipControlsFgOver; diff --git a/Telegram/SourceFiles/editor/photo_editor.cpp b/Telegram/SourceFiles/editor/photo_editor.cpp index 24dcde3a8..5d29d7413 100644 --- a/Telegram/SourceFiles/editor/photo_editor.cpp +++ b/Telegram/SourceFiles/editor/photo_editor.cpp @@ -92,11 +92,15 @@ PhotoEditor::PhotoEditor( _colorPicker->moveLine(p); }, _controls->lifetime()); + _controls->colorLineShownValue( + ) | rpl::start_with_next([=](bool shown) { + _colorPicker->setVisible(shown); + }, _controls->lifetime()); + _mode.value( ) | rpl::start_with_next([=](const PhotoEditorMode &mode) { _content->applyMode(mode); _controls->applyMode(mode); - _colorPicker->setVisible(mode.mode == PhotoEditorMode::Mode::Paint); }, lifetime()); _controls->rotateRequests( diff --git a/Telegram/SourceFiles/editor/photo_editor_controls.cpp b/Telegram/SourceFiles/editor/photo_editor_controls.cpp index 72e92f3e9..eb6987082 100644 --- a/Telegram/SourceFiles/editor/photo_editor_controls.cpp +++ b/Telegram/SourceFiles/editor/photo_editor_controls.cpp @@ -248,19 +248,13 @@ PhotoEditorControls::PhotoEditorControls( } _paintModeButtonActive->setAttribute(Qt::WA_TransparentForMouseEvents); - rpl::combine( - sizeValue(), - _mode.value() - ) | rpl::start_with_next([=]( - const QSize &size, - const PhotoEditorMode &mode) { + sizeValue( + ) | rpl::start_with_next([=](const QSize &size) { if (size.isEmpty()) { return; } - const auto buttonsTop = size.height() - - st::photoEditorControlsBottomSkip - - _transformButtons->height(); + const auto buttonsTop = bottomButtonsTop(); const auto ¤t = _transformButtons->isHidden() ? _paintBottomButtons @@ -271,6 +265,15 @@ PhotoEditorControls::PhotoEditorControls( buttonsTop); }, lifetime()); + _mode.changes( + ) | rpl::start_with_next([=](const PhotoEditorMode &mode) { + const auto animated = (_paintBottomButtons->isVisible() + == _transformButtons->isVisible()) + ? anim::type::instant + : anim::type::normal; + showAnimated(mode.mode, animated); + }, lifetime()); + _paintBottomButtons->positionValue( ) | rpl::start_with_next([=](const QPoint &containerPos) { _paintTopButtons->moveToLeft( @@ -280,6 +283,11 @@ PhotoEditorControls::PhotoEditorControls( - _paintTopButtons->height()); }, _paintBottomButtons->lifetime()); + _paintBottomButtons->shownValue( + ) | rpl::start_with_next([=](bool shown) { + _paintTopButtons->setVisible(shown); + }, _paintBottomButtons->lifetime()); + controllers->undoController->setPerformRequestChanges(rpl::merge( _undoButton->clicks() | rpl::map_to(Undo::Undo), _redoButton->clicks() | rpl::map_to(Undo::Redo))); @@ -358,11 +366,81 @@ rpl::producer<> PhotoEditorControls::cancelRequests() const { _paintCancel->clicks() | rpl::to_empty); } -void PhotoEditorControls::applyMode(const PhotoEditorMode &mode) { +int PhotoEditorControls::bottomButtonsTop() const { + return height() + - st::photoEditorControlsBottomSkip + - _transformButtons->height(); +} + +void PhotoEditorControls::showAnimated( + PhotoEditorMode::Mode mode, + anim::type animated) { using Mode = PhotoEditorMode::Mode; - _transformButtons->setVisible(mode.mode == Mode::Transform); - _paintBottomButtons->setVisible(mode.mode == Mode::Paint); - _paintTopButtons->setVisible(mode.mode == Mode::Paint); + + const auto duration = st::photoEditorBarAnimationDuration; + + const auto isTransform = (mode == Mode::Transform); + const auto isPaint = (mode == Mode::Paint); + + const auto buttonsLeft = (width() - _transformButtons->width()) / 2; + const auto buttonsTop = bottomButtonsTop(); + + const auto visibleBar = _transformButtons->isVisible() + ? _transformButtons.get() + : _paintBottomButtons.get(); + + const auto shouldVisibleBar = isTransform + ? _transformButtons.get() + : _paintBottomButtons.get(); // Mode::Paint + + const auto computeTop = [=](float64 progress) { + return anim::interpolate(buttonsTop, height() * 2, progress); + }; + + const auto showShouldVisibleBar = [=] { + _toggledBarAnimation.stop(); + auto callback = [=](float64 value) { + shouldVisibleBar->moveToLeft(buttonsLeft, computeTop(value)); + }; + if (animated == anim::type::instant) { + callback(1.); + } else { + _toggledBarAnimation.start( + std::move(callback), + 1., + 0., + duration); + } + }; + + auto animationCallback = [=](float64 value) { + if (shouldVisibleBar == visibleBar) { + showShouldVisibleBar(); + return; + } + visibleBar->moveToLeft(buttonsLeft, computeTop(value)); + + if (value == 1.) { + shouldVisibleBar->show(); + shouldVisibleBar->moveToLeft(buttonsLeft, computeTop(1.)); + visibleBar->hide(); + + showShouldVisibleBar(); + } + }; + + if (animated == anim::type::instant) { + animationCallback(1.); + } else { + _toggledBarAnimation.start( + std::move(animationCallback), + 0., + 1., + duration); + } +} + +void PhotoEditorControls::applyMode(const PhotoEditorMode &mode) { _mode = mode; } @@ -377,4 +455,8 @@ rpl::producer PhotoEditorControls::colorLinePositionValue() const { }); } +rpl::producer PhotoEditorControls::colorLineShownValue() const { + return _paintTopButtons->shownValue(); +} + } // namespace Editor diff --git a/Telegram/SourceFiles/editor/photo_editor_controls.h b/Telegram/SourceFiles/editor/photo_editor_controls.h index 829fa051c..fac27dadc 100644 --- a/Telegram/SourceFiles/editor/photo_editor_controls.h +++ b/Telegram/SourceFiles/editor/photo_editor_controls.h @@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/rp_widget.h" +#include "ui/effects/animations.h" #include "editor/photo_editor_common.h" namespace Ui { @@ -35,10 +36,16 @@ public: [[nodiscard]] rpl::producer<> doneRequests() const; [[nodiscard]] rpl::producer<> cancelRequests() const; [[nodiscard]] rpl::producer colorLinePositionValue() const; + [[nodiscard]] rpl::producer colorLineShownValue() const; void applyMode(const PhotoEditorMode &mode); private: + void showAnimated( + PhotoEditorMode::Mode mode, + anim::type animated = anim::type::normal); + + int bottomButtonsTop() const; const style::color &_bg; const int _buttonHeight; @@ -61,6 +68,8 @@ private: bool _flipped = false; + Ui::Animations::Simple _toggledBarAnimation; + rpl::variable _mode; };