2021-02-05 05:44:04 +00:00
|
|
|
/*
|
|
|
|
This file is part of Telegram Desktop,
|
|
|
|
the official desktop application for the Telegram messaging service.
|
|
|
|
|
|
|
|
For license and copyright information please follow this link:
|
|
|
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|
|
|
*/
|
|
|
|
#include "editor/photo_editor_controls.h"
|
|
|
|
|
2021-03-21 12:38:33 +00:00
|
|
|
#include "editor/controllers/controllers.h"
|
2021-02-13 08:23:21 +00:00
|
|
|
#include "lang/lang_keys.h"
|
|
|
|
#include "ui/image/image_prepare.h"
|
2021-02-05 09:24:26 +00:00
|
|
|
#include "ui/widgets/buttons.h"
|
2022-12-22 12:41:17 +00:00
|
|
|
#include "ui/widgets/labels.h"
|
|
|
|
#include "ui/wrap/fade_wrap.h"
|
2022-09-16 20:23:27 +00:00
|
|
|
#include "ui/painter.h"
|
2021-02-05 09:24:26 +00:00
|
|
|
#include "styles/style_editor.h"
|
|
|
|
|
2021-02-05 05:44:04 +00:00
|
|
|
namespace Editor {
|
|
|
|
|
2021-02-13 08:23:21 +00:00
|
|
|
class EdgeButton final : public Ui::RippleButton {
|
|
|
|
public:
|
|
|
|
EdgeButton(
|
|
|
|
not_null<Ui::RpWidget*> parent,
|
|
|
|
const QString &text,
|
|
|
|
int height,
|
|
|
|
bool left,
|
|
|
|
const style::color &bg,
|
|
|
|
const style::color &fg,
|
|
|
|
const style::RippleAnimation &st);
|
|
|
|
|
|
|
|
protected:
|
|
|
|
QImage prepareRippleMask() const override;
|
|
|
|
QPoint prepareRippleStartPosition() const override;
|
|
|
|
|
|
|
|
private:
|
|
|
|
void init();
|
|
|
|
|
|
|
|
const style::color &_fg;
|
|
|
|
Ui::Text::String _text;
|
|
|
|
const int _width;
|
|
|
|
const QRect _rippleRect;
|
|
|
|
const QColor _bg;
|
|
|
|
const bool _left;
|
|
|
|
|
|
|
|
QImage rounded(std::optional<QColor> color) const;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
EdgeButton::EdgeButton(
|
|
|
|
not_null<Ui::RpWidget*> parent,
|
|
|
|
const QString &text,
|
|
|
|
int height,
|
|
|
|
bool left,
|
|
|
|
const style::color &bg,
|
|
|
|
const style::color &fg,
|
|
|
|
const style::RippleAnimation &st)
|
|
|
|
: Ui::RippleButton(parent, st)
|
|
|
|
, _fg(fg)
|
2022-12-22 12:41:17 +00:00
|
|
|
, _text(st::photoEditorButtonStyle, text)
|
2021-02-13 08:23:21 +00:00
|
|
|
, _width(_text.maxWidth()
|
|
|
|
+ st::photoEditorTextButtonPadding.left()
|
|
|
|
+ st::photoEditorTextButtonPadding.right())
|
|
|
|
, _rippleRect(QRect(0, 0, _width, height))
|
|
|
|
, _bg(bg->c)
|
|
|
|
, _left(left) {
|
|
|
|
resize(_width, height);
|
|
|
|
init();
|
|
|
|
}
|
|
|
|
|
|
|
|
void EdgeButton::init() {
|
2021-05-02 09:16:12 +00:00
|
|
|
// const auto bg = rounded(_bg);
|
2021-02-13 08:23:21 +00:00
|
|
|
|
|
|
|
paintRequest(
|
|
|
|
) | rpl::start_with_next([=] {
|
|
|
|
Painter p(this);
|
|
|
|
|
2021-05-02 09:16:12 +00:00
|
|
|
// p.drawImage(QPoint(), bg);
|
2021-02-13 08:23:21 +00:00
|
|
|
|
|
|
|
paintRipple(p, _rippleRect.x(), _rippleRect.y());
|
|
|
|
|
|
|
|
p.setPen(_fg);
|
2022-12-22 12:41:17 +00:00
|
|
|
const auto textTop = st::photoEditorButtonTextTop;
|
2021-02-13 08:23:21 +00:00
|
|
|
_text.draw(p, 0, textTop, width(), style::al_center);
|
|
|
|
}, lifetime());
|
|
|
|
}
|
|
|
|
|
|
|
|
QImage EdgeButton::rounded(std::optional<QColor> color) const {
|
|
|
|
auto result = QImage(
|
|
|
|
_rippleRect.size() * cIntRetinaFactor(),
|
|
|
|
QImage::Format_ARGB32_Premultiplied);
|
|
|
|
result.setDevicePixelRatio(cIntRetinaFactor());
|
|
|
|
result.fill(color.value_or(Qt::white));
|
|
|
|
|
2022-01-21 12:31:39 +00:00
|
|
|
const auto parts = RectPart::None
|
|
|
|
| (_left ? RectPart::TopLeft : RectPart::TopRight)
|
|
|
|
| (_left ? RectPart::BottomLeft : RectPart::BottomRight);
|
|
|
|
return Images::Round(std::move(result), ImageRoundRadius::Large, parts);
|
2021-02-13 08:23:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
QImage EdgeButton::prepareRippleMask() const {
|
|
|
|
return rounded(std::nullopt);
|
|
|
|
}
|
|
|
|
|
|
|
|
QPoint EdgeButton::prepareRippleStartPosition() const {
|
|
|
|
return mapFromGlobal(QCursor::pos()) - _rippleRect.topLeft();
|
|
|
|
}
|
|
|
|
|
2021-05-02 09:16:12 +00:00
|
|
|
class ButtonBar final : public Ui::RpWidget {
|
2021-02-05 08:58:10 +00:00
|
|
|
public:
|
2021-05-02 09:16:12 +00:00
|
|
|
ButtonBar(
|
|
|
|
not_null<Ui::RpWidget*> parent,
|
|
|
|
const style::color &bg);
|
2021-02-05 08:58:10 +00:00
|
|
|
|
2021-05-02 09:16:12 +00:00
|
|
|
private:
|
|
|
|
QImage _roundedBg;
|
2021-02-05 08:58:10 +00:00
|
|
|
|
|
|
|
};
|
|
|
|
|
2021-05-02 09:16:12 +00:00
|
|
|
ButtonBar::ButtonBar(
|
|
|
|
not_null<Ui::RpWidget*> parent,
|
|
|
|
const style::color &bg)
|
2021-02-05 05:44:04 +00:00
|
|
|
: RpWidget(parent) {
|
2021-05-02 09:16:12 +00:00
|
|
|
sizeValue(
|
|
|
|
) | rpl::start_with_next([=](const QSize &size) {
|
|
|
|
const auto children = RpWidget::children();
|
2021-07-11 20:16:28 +00:00
|
|
|
const auto widgets = ranges::views::all(
|
2021-05-02 09:16:12 +00:00
|
|
|
children
|
2021-07-11 20:16:28 +00:00
|
|
|
) | ranges::views::filter([](not_null<const QObject*> object) {
|
2021-05-02 09:16:12 +00:00
|
|
|
return object->isWidgetType();
|
2021-07-11 20:16:28 +00:00
|
|
|
}) | ranges::views::transform([](not_null<QObject*> object) {
|
2022-12-22 12:41:17 +00:00
|
|
|
return static_cast<QWidget*>(object.get());
|
2021-05-02 09:16:12 +00:00
|
|
|
}) | ranges::to_vector;
|
2022-12-22 12:41:17 +00:00
|
|
|
if (widgets.size() < 2) {
|
|
|
|
return;
|
|
|
|
}
|
2021-05-02 09:16:12 +00:00
|
|
|
|
2022-12-22 12:41:17 +00:00
|
|
|
const auto layout = [&](bool symmetrical) {
|
|
|
|
auto widths = widgets | ranges::views::transform(
|
|
|
|
&QWidget::width
|
|
|
|
) | ranges::to_vector;
|
|
|
|
const auto count = int(widths.size());
|
|
|
|
const auto middle = count / 2;
|
|
|
|
if (symmetrical) {
|
|
|
|
for (auto i = 0; i != middle; ++i) {
|
|
|
|
const auto j = count - i - 1;
|
|
|
|
widths[i] = widths[j] = std::max(widths[i], widths[j]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const auto residualWidth = size.width()
|
|
|
|
- ranges::accumulate(widths, 0);
|
|
|
|
if (symmetrical && residualWidth < 0) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
const auto step = residualWidth / float(count - 1);
|
|
|
|
|
|
|
|
auto left = 0.;
|
|
|
|
auto &&ints = ranges::views::ints(0, ranges::unreachable);
|
|
|
|
auto &&list = ranges::views::zip(widgets, widths, ints);
|
|
|
|
for (const auto &[widget, width, index] : list) {
|
|
|
|
widget->move(int((index >= middle)
|
|
|
|
? (left + width - widget->width())
|
|
|
|
: left), 0);
|
|
|
|
left += width + step;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
};
|
|
|
|
if (!layout(true)) {
|
|
|
|
layout(false);
|
2021-05-02 09:16:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
auto result = QImage(
|
|
|
|
size * cIntRetinaFactor(),
|
|
|
|
QImage::Format_ARGB32_Premultiplied);
|
|
|
|
result.setDevicePixelRatio(cIntRetinaFactor());
|
|
|
|
result.fill(bg->c);
|
|
|
|
|
2022-01-21 12:31:39 +00:00
|
|
|
_roundedBg = Images::Round(
|
|
|
|
std::move(result),
|
|
|
|
ImageRoundRadius::Large);
|
2021-05-02 09:16:12 +00:00
|
|
|
}, lifetime());
|
|
|
|
|
|
|
|
paintRequest(
|
|
|
|
) | rpl::start_with_next([=] {
|
2022-09-16 20:23:27 +00:00
|
|
|
auto p = QPainter(this);
|
2021-05-02 09:16:12 +00:00
|
|
|
p.drawImage(QPoint(), _roundedBg);
|
|
|
|
}, lifetime());
|
2021-02-05 08:58:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
PhotoEditorControls::PhotoEditorControls(
|
|
|
|
not_null<Ui::RpWidget*> parent,
|
2021-02-23 10:34:12 +00:00
|
|
|
std::shared_ptr<Controllers> controllers,
|
2021-02-22 08:14:23 +00:00
|
|
|
const PhotoModifications modifications,
|
2022-12-22 12:41:17 +00:00
|
|
|
const EditorData &data)
|
2021-02-05 08:58:10 +00:00
|
|
|
: RpWidget(parent)
|
2021-04-03 14:58:49 +00:00
|
|
|
, _bg(st::roundedBg)
|
2021-05-02 09:16:12 +00:00
|
|
|
, _buttonHeight(st::photoEditorButtonBarHeight)
|
|
|
|
, _transformButtons(base::make_unique_q<ButtonBar>(this, _bg))
|
2021-05-03 17:04:27 +00:00
|
|
|
, _paintTopButtons(base::make_unique_q<ButtonBar>(this, _bg))
|
2021-05-02 09:16:12 +00:00
|
|
|
, _paintBottomButtons(base::make_unique_q<ButtonBar>(this, _bg))
|
2022-12-22 12:41:17 +00:00
|
|
|
, _about(data.about.empty()
|
|
|
|
? nullptr
|
|
|
|
: base::make_unique_q<Ui::FadeWrap<Ui::FlatLabel>>(
|
|
|
|
this,
|
|
|
|
object_ptr<Ui::FlatLabel>(
|
|
|
|
this,
|
|
|
|
rpl::single(data.about),
|
|
|
|
st::photoEditorAbout)))
|
2021-05-02 09:16:12 +00:00
|
|
|
, _transformCancel(base::make_unique_q<EdgeButton>(
|
|
|
|
_transformButtons,
|
|
|
|
tr::lng_cancel(tr::now),
|
|
|
|
_buttonHeight,
|
|
|
|
true,
|
|
|
|
_bg,
|
2022-12-22 12:41:17 +00:00
|
|
|
st::mediaviewCaptionFg,
|
2021-05-02 09:16:12 +00:00
|
|
|
st::photoEditorRotateButton.ripple))
|
2021-02-05 09:24:26 +00:00
|
|
|
, _flipButton(base::make_unique_q<Ui::IconButton>(
|
2021-03-14 09:39:55 +00:00
|
|
|
_transformButtons,
|
2021-02-13 04:29:31 +00:00
|
|
|
st::photoEditorFlipButton))
|
2022-12-22 12:41:17 +00:00
|
|
|
, _rotateButton(base::make_unique_q<Ui::IconButton>(
|
|
|
|
_transformButtons,
|
|
|
|
st::photoEditorRotateButton))
|
2021-02-13 04:29:31 +00:00
|
|
|
, _paintModeButton(base::make_unique_q<Ui::IconButton>(
|
2021-03-14 09:39:55 +00:00
|
|
|
_transformButtons,
|
|
|
|
st::photoEditorPaintModeButton))
|
2021-05-02 09:16:12 +00:00
|
|
|
, _transformDone(base::make_unique_q<EdgeButton>(
|
|
|
|
_transformButtons,
|
2022-12-22 12:41:17 +00:00
|
|
|
(data.confirm.isEmpty() ? tr::lng_box_done(tr::now) : data.confirm),
|
2021-05-02 09:16:12 +00:00
|
|
|
_buttonHeight,
|
|
|
|
false,
|
|
|
|
_bg,
|
2022-12-22 12:41:17 +00:00
|
|
|
st::mediaviewTextLinkFg,
|
2021-05-02 09:16:12 +00:00
|
|
|
st::photoEditorRotateButton.ripple))
|
|
|
|
, _paintCancel(base::make_unique_q<EdgeButton>(
|
|
|
|
_paintBottomButtons,
|
|
|
|
tr::lng_cancel(tr::now),
|
|
|
|
_buttonHeight,
|
|
|
|
true,
|
|
|
|
_bg,
|
2022-12-22 12:41:17 +00:00
|
|
|
st::mediaviewCaptionFg,
|
2021-05-02 09:16:12 +00:00
|
|
|
st::photoEditorRotateButton.ripple))
|
2021-03-14 09:39:55 +00:00
|
|
|
, _undoButton(base::make_unique_q<Ui::IconButton>(
|
2021-05-03 17:04:27 +00:00
|
|
|
_paintTopButtons,
|
2021-03-14 09:39:55 +00:00
|
|
|
st::photoEditorUndoButton))
|
|
|
|
, _redoButton(base::make_unique_q<Ui::IconButton>(
|
2021-05-03 17:04:27 +00:00
|
|
|
_paintTopButtons,
|
2021-03-14 09:39:55 +00:00
|
|
|
st::photoEditorRedoButton))
|
|
|
|
, _paintModeButtonActive(base::make_unique_q<Ui::IconButton>(
|
2021-05-02 09:16:12 +00:00
|
|
|
_paintBottomButtons,
|
2021-02-13 08:23:21 +00:00
|
|
|
st::photoEditorPaintModeButton))
|
2021-02-23 10:35:23 +00:00
|
|
|
, _stickersButton(controllers->stickersPanelController
|
|
|
|
? base::make_unique_q<Ui::IconButton>(
|
2021-05-02 09:16:12 +00:00
|
|
|
_paintBottomButtons,
|
2021-02-23 10:35:23 +00:00
|
|
|
st::photoEditorStickersButton)
|
|
|
|
: nullptr)
|
2021-05-02 09:16:12 +00:00
|
|
|
, _paintDone(base::make_unique_q<EdgeButton>(
|
|
|
|
_paintBottomButtons,
|
2021-02-13 08:23:21 +00:00
|
|
|
tr::lng_box_done(tr::now),
|
2021-05-02 09:16:12 +00:00
|
|
|
_buttonHeight,
|
2021-02-13 08:23:21 +00:00
|
|
|
false,
|
|
|
|
_bg,
|
2022-12-22 12:41:17 +00:00
|
|
|
st::mediaviewTextLinkFg,
|
2021-04-03 14:58:49 +00:00
|
|
|
st::photoEditorRotateButton.ripple)) {
|
2021-02-05 08:58:10 +00:00
|
|
|
|
2021-04-03 14:58:49 +00:00
|
|
|
{
|
|
|
|
const auto icon = &st::photoEditorPaintIconActive;
|
|
|
|
_paintModeButtonActive->setIconOverride(icon, icon);
|
|
|
|
}
|
2021-03-14 09:39:55 +00:00
|
|
|
_paintModeButtonActive->setAttribute(Qt::WA_TransparentForMouseEvents);
|
2021-02-05 08:58:10 +00:00
|
|
|
|
2021-05-04 16:42:47 +00:00
|
|
|
sizeValue(
|
|
|
|
) | rpl::start_with_next([=](const QSize &size) {
|
2021-03-14 09:39:55 +00:00
|
|
|
if (size.isEmpty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-12-22 12:41:17 +00:00
|
|
|
const auto &padding = st::photoEditorButtonBarPadding;
|
|
|
|
const auto w = std::min(st::photoEditorButtonBarWidth, size.width())
|
|
|
|
- padding.left()
|
|
|
|
- padding.right();
|
|
|
|
_transformButtons->resize(w, _buttonHeight);
|
|
|
|
_paintBottomButtons->resize(w, _buttonHeight);
|
|
|
|
_paintTopButtons->resize(w, _buttonHeight);
|
|
|
|
|
2021-05-04 16:42:47 +00:00
|
|
|
const auto buttonsTop = bottomButtonsTop();
|
2021-05-02 09:24:48 +00:00
|
|
|
|
2021-03-14 09:39:55 +00:00
|
|
|
const auto ¤t = _transformButtons->isHidden()
|
2021-05-02 09:16:12 +00:00
|
|
|
? _paintBottomButtons
|
2021-03-14 09:39:55 +00:00
|
|
|
: _transformButtons;
|
2021-02-05 08:58:10 +00:00
|
|
|
|
2021-03-14 09:39:55 +00:00
|
|
|
current->moveToLeft(
|
|
|
|
(size.width() - current->width()) / 2,
|
2021-02-16 03:45:05 +00:00
|
|
|
buttonsTop);
|
2022-12-22 12:41:17 +00:00
|
|
|
|
|
|
|
if (_about) {
|
|
|
|
const auto &margin = st::photoEditorAboutMargin;
|
|
|
|
const auto skip = st::photoEditorCropPointSize;
|
|
|
|
_about->resizeToWidth(
|
|
|
|
size.width() - margin.left() - margin.right());
|
|
|
|
_about->moveToLeft(
|
|
|
|
(size.width() - _about->width()) / 2,
|
|
|
|
margin.top() - skip);
|
|
|
|
}
|
2021-02-05 08:58:10 +00:00
|
|
|
}, lifetime());
|
|
|
|
|
2021-05-04 16:42:47 +00:00
|
|
|
_mode.changes(
|
|
|
|
) | rpl::start_with_next([=](const PhotoEditorMode &mode) {
|
2021-07-07 18:14:50 +00:00
|
|
|
if (mode.mode == PhotoEditorMode::Mode::Out) {
|
|
|
|
return;
|
|
|
|
}
|
2021-05-04 16:42:47 +00:00
|
|
|
const auto animated = (_paintBottomButtons->isVisible()
|
|
|
|
== _transformButtons->isVisible())
|
|
|
|
? anim::type::instant
|
|
|
|
: anim::type::normal;
|
|
|
|
showAnimated(mode.mode, animated);
|
|
|
|
}, lifetime());
|
|
|
|
|
2021-05-03 17:04:27 +00:00
|
|
|
_paintBottomButtons->positionValue(
|
|
|
|
) | rpl::start_with_next([=](const QPoint &containerPos) {
|
|
|
|
_paintTopButtons->moveToLeft(
|
|
|
|
containerPos.x(),
|
|
|
|
containerPos.y()
|
|
|
|
- st::photoEditorControlsCenterSkip
|
|
|
|
- _paintTopButtons->height());
|
|
|
|
}, _paintBottomButtons->lifetime());
|
|
|
|
|
2021-05-04 16:42:47 +00:00
|
|
|
_paintBottomButtons->shownValue(
|
|
|
|
) | rpl::start_with_next([=](bool shown) {
|
|
|
|
_paintTopButtons->setVisible(shown);
|
|
|
|
}, _paintBottomButtons->lifetime());
|
|
|
|
|
2021-02-23 10:34:12 +00:00
|
|
|
controllers->undoController->setPerformRequestChanges(rpl::merge(
|
2021-03-14 09:42:18 +00:00
|
|
|
_undoButton->clicks() | rpl::map_to(Undo::Undo),
|
2022-01-04 16:48:27 +00:00
|
|
|
_redoButton->clicks() | rpl::map_to(Undo::Redo),
|
|
|
|
_keyPresses.events(
|
|
|
|
) | rpl::filter([=](not_null<QKeyEvent*> e) {
|
|
|
|
using Mode = PhotoEditorMode::Mode;
|
|
|
|
return (e->matches(QKeySequence::Undo)
|
|
|
|
&& !_undoButton->isHidden()
|
|
|
|
&& !_undoButton->testAttribute(
|
|
|
|
Qt::WA_TransparentForMouseEvents)
|
|
|
|
&& (_mode.current().mode == Mode::Paint))
|
|
|
|
|| (e->matches(QKeySequence::Redo)
|
|
|
|
&& !_redoButton->isHidden()
|
|
|
|
&& !_redoButton->testAttribute(
|
|
|
|
Qt::WA_TransparentForMouseEvents)
|
|
|
|
&& (_mode.current().mode == Mode::Paint));
|
|
|
|
}) | rpl::map([=](not_null<QKeyEvent*> e) {
|
|
|
|
return e->matches(QKeySequence::Undo) ? Undo::Undo : Undo::Redo;
|
|
|
|
})));
|
2021-03-14 09:42:18 +00:00
|
|
|
|
2021-02-23 10:34:12 +00:00
|
|
|
controllers->undoController->canPerformChanges(
|
2021-03-14 09:42:18 +00:00
|
|
|
) | rpl::start_with_next([=](const UndoController::EnableRequest &r) {
|
|
|
|
const auto isUndo = (r.command == Undo::Undo);
|
|
|
|
const auto &button = isUndo ? _undoButton : _redoButton;
|
|
|
|
button->setAttribute(Qt::WA_TransparentForMouseEvents, !r.enable);
|
|
|
|
if (!r.enable) {
|
|
|
|
button->clearState();
|
|
|
|
}
|
|
|
|
|
|
|
|
button->setIconOverride(r.enable
|
|
|
|
? nullptr
|
|
|
|
: isUndo
|
|
|
|
? &st::photoEditorUndoButtonInactive
|
|
|
|
: &st::photoEditorRedoButtonInactive);
|
|
|
|
}, lifetime());
|
|
|
|
|
2021-02-23 10:35:23 +00:00
|
|
|
if (_stickersButton) {
|
2021-05-04 17:57:52 +00:00
|
|
|
using ShowRequest = StickersPanelController::ShowRequest;
|
|
|
|
|
2021-02-23 10:35:23 +00:00
|
|
|
controllers->stickersPanelController->setShowRequestChanges(
|
2021-05-04 17:57:52 +00:00
|
|
|
rpl::merge(
|
|
|
|
_mode.value(
|
|
|
|
) | rpl::map_to(ShowRequest::HideFast),
|
|
|
|
_stickersButton->clicks(
|
|
|
|
) | rpl::map_to(ShowRequest::ToggleAnimated)
|
|
|
|
));
|
2021-02-23 10:35:23 +00:00
|
|
|
|
|
|
|
controllers->stickersPanelController->setMoveRequestChanges(
|
2021-05-02 09:16:12 +00:00
|
|
|
_paintBottomButtons->positionValue(
|
2021-02-23 10:35:23 +00:00
|
|
|
) | rpl::map([=](const QPoint &containerPos) {
|
|
|
|
return QPoint(
|
|
|
|
(x() + width()) / 2,
|
|
|
|
y() + containerPos.y() + _stickersButton->y());
|
|
|
|
}));
|
|
|
|
|
|
|
|
controllers->stickersPanelController->panelShown(
|
|
|
|
) | rpl::start_with_next([=](bool shown) {
|
2021-04-03 14:58:49 +00:00
|
|
|
const auto icon = shown
|
|
|
|
? &st::photoEditorStickersIconActive
|
|
|
|
: nullptr;
|
|
|
|
_stickersButton->setIconOverride(icon, icon);
|
2021-02-23 10:35:23 +00:00
|
|
|
}, _stickersButton->lifetime());
|
|
|
|
}
|
|
|
|
|
2022-03-11 05:55:21 +00:00
|
|
|
rpl::single(rpl::empty) | rpl::skip(
|
|
|
|
modifications.flipped ? 0 : 1
|
|
|
|
) | rpl::then(
|
2021-04-03 14:58:49 +00:00
|
|
|
_flipButton->clicks() | rpl::to_empty
|
2021-02-22 08:14:23 +00:00
|
|
|
) | rpl::start_with_next([=] {
|
|
|
|
_flipped = !_flipped;
|
2021-04-03 14:58:49 +00:00
|
|
|
const auto icon = _flipped ? &st::photoEditorFlipIconActive : nullptr;
|
|
|
|
_flipButton->setIconOverride(icon, icon);
|
2021-02-22 08:14:23 +00:00
|
|
|
}, _flipButton->lifetime());
|
|
|
|
|
2021-02-05 08:58:10 +00:00
|
|
|
}
|
2021-02-07 23:10:30 +00:00
|
|
|
|
|
|
|
rpl::producer<int> PhotoEditorControls::rotateRequests() const {
|
2021-02-13 08:23:21 +00:00
|
|
|
return _rotateButton->clicks() | rpl::map_to(90);
|
2021-02-07 23:10:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
rpl::producer<> PhotoEditorControls::flipRequests() const {
|
|
|
|
return _flipButton->clicks() | rpl::to_empty;
|
|
|
|
}
|
|
|
|
|
2021-02-13 04:29:31 +00:00
|
|
|
rpl::producer<> PhotoEditorControls::paintModeRequests() const {
|
|
|
|
return _paintModeButton->clicks() | rpl::to_empty;
|
|
|
|
}
|
|
|
|
|
2021-03-14 09:39:55 +00:00
|
|
|
rpl::producer<> PhotoEditorControls::doneRequests() const {
|
2021-05-02 09:16:12 +00:00
|
|
|
return rpl::merge(
|
|
|
|
_transformDone->clicks() | rpl::to_empty,
|
2021-05-04 22:38:55 +00:00
|
|
|
_paintDone->clicks() | rpl::to_empty,
|
|
|
|
_keyPresses.events(
|
2022-01-04 16:48:27 +00:00
|
|
|
) | rpl::filter([=](not_null<QKeyEvent*> e) {
|
|
|
|
const auto key = e->key();
|
2021-05-04 22:38:55 +00:00
|
|
|
return ((key == Qt::Key_Enter) || (key == Qt::Key_Return))
|
|
|
|
&& !_toggledBarAnimation.animating();
|
|
|
|
}) | rpl::to_empty);
|
2021-03-14 09:39:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
rpl::producer<> PhotoEditorControls::cancelRequests() const {
|
2021-05-02 09:16:12 +00:00
|
|
|
return rpl::merge(
|
|
|
|
_transformCancel->clicks() | rpl::to_empty,
|
2021-05-04 22:38:55 +00:00
|
|
|
_paintCancel->clicks() | rpl::to_empty,
|
|
|
|
_keyPresses.events(
|
2022-01-04 16:48:27 +00:00
|
|
|
) | rpl::filter([=](not_null<QKeyEvent*> e) {
|
|
|
|
const auto key = e->key();
|
2021-05-04 22:38:55 +00:00
|
|
|
return (key == Qt::Key_Escape)
|
|
|
|
&& !_toggledBarAnimation.animating();
|
|
|
|
}) | rpl::to_empty);
|
2021-03-14 09:39:55 +00:00
|
|
|
}
|
|
|
|
|
2021-05-04 16:42:47 +00:00
|
|
|
int PhotoEditorControls::bottomButtonsTop() const {
|
|
|
|
return height()
|
|
|
|
- st::photoEditorControlsBottomSkip
|
|
|
|
- _transformButtons->height();
|
|
|
|
}
|
|
|
|
|
|
|
|
void PhotoEditorControls::showAnimated(
|
|
|
|
PhotoEditorMode::Mode mode,
|
|
|
|
anim::type animated) {
|
2021-03-14 09:39:55 +00:00
|
|
|
using Mode = PhotoEditorMode::Mode;
|
2021-05-04 16:42:47 +00:00
|
|
|
|
|
|
|
const auto duration = st::photoEditorBarAnimationDuration;
|
|
|
|
|
|
|
|
const auto isTransform = (mode == Mode::Transform);
|
2022-12-22 12:41:17 +00:00
|
|
|
if (_about) {
|
|
|
|
_about->toggle(isTransform, animated);
|
|
|
|
}
|
2021-05-04 16:42:47 +00:00
|
|
|
|
|
|
|
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) {
|
2021-03-14 09:39:55 +00:00
|
|
|
_mode = mode;
|
|
|
|
}
|
|
|
|
|
2021-05-03 17:04:27 +00:00
|
|
|
rpl::producer<QPoint> PhotoEditorControls::colorLinePositionValue() const {
|
|
|
|
return rpl::merge(
|
|
|
|
geometryValue() | rpl::to_empty,
|
|
|
|
_paintTopButtons->geometryValue() | rpl::to_empty
|
|
|
|
) | rpl::map([=] {
|
|
|
|
const auto r = _paintTopButtons->geometry();
|
|
|
|
return mapToParent(r.topLeft())
|
|
|
|
+ QPoint(r.width() / 2, r.height() / 2);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-05-04 16:42:47 +00:00
|
|
|
rpl::producer<bool> PhotoEditorControls::colorLineShownValue() const {
|
|
|
|
return _paintTopButtons->shownValue();
|
|
|
|
}
|
|
|
|
|
2021-05-04 22:38:55 +00:00
|
|
|
bool PhotoEditorControls::handleKeyPress(not_null<QKeyEvent*> e) const {
|
2022-01-04 16:48:27 +00:00
|
|
|
_keyPresses.fire(std::move(e));
|
2021-05-04 22:38:55 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool PhotoEditorControls::animating() const {
|
|
|
|
return _toggledBarAnimation.animating();
|
|
|
|
}
|
|
|
|
|
2021-02-05 05:44:04 +00:00
|
|
|
} // namespace Editor
|