ZaStoGram_desktop/Telegram/SourceFiles/editor/editor_trim_timeline.h

207 lines
5.4 KiB
C++

/*
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
*/
#pragma once
#include "base/unique_qptr.h"
#include "base/weak_ptr.h"
#include "ui/effects/animations.h"
#include "ui/rp_widget.h"
#include "ui/ui_utility.h"
namespace Ui {
class MaskedInputField;
} // namespace Ui
namespace Editor {
struct TrimTimelineDescriptor {
crl::time duration = 0;
crl::time maxDuration = 0;
crl::time minDuration = 0;
// A zero |till| means the whole allowed window is selected.
crl::time from = 0;
crl::time till = 0;
crl::time cover = 0;
bool trimOnly = false;
};
class TrimTimeline
: public Ui::RpWidget
, public base::has_weak_ptr {
public:
TrimTimeline(
not_null<Ui::RpWidget*> parent,
TrimTimelineDescriptor descriptor);
[[nodiscard]] crl::time from() const {
return _from;
}
[[nodiscard]] crl::time till() const {
return _till;
}
[[nodiscard]] crl::time cover() const {
return _cover;
}
[[nodiscard]] crl::time playbackPosition() const {
return _playback;
}
[[nodiscard]] float64 zoom() const {
return _zoom;
}
[[nodiscard]] crl::time visibleFrom() const;
[[nodiscard]] crl::time visibleTill() const;
[[nodiscard]] rpl::producer<crl::time> trimChanges() const {
return _trimChanges.events();
}
[[nodiscard]] rpl::producer<crl::time> coverChanges() const {
return _coverChanges.events();
}
[[nodiscard]] rpl::producer<bool> draggingChanges() const {
return _draggingChanges.events();
}
void setTrim(crl::time from, crl::time till);
void setPlaybackPosition(crl::time position);
void commitPendingEdit();
void setSizeLabel(const QString &text);
[[nodiscard]] bool draggingHead() const;
[[nodiscard]] int resizeGetHeight(int newWidth) override;
protected:
[[nodiscard]] crl::time duration() const {
return _duration;
}
[[nodiscard]] bool trimOnly() const {
return _trimOnly;
}
[[nodiscard]] QRect stripRect() const;
[[nodiscard]] crl::time timeAt(int x) const;
[[nodiscard]] int xAt(crl::time time) const;
[[nodiscard]] float64 visibleSpan() const;
virtual void paintStrip(QPainter &p, const QRect &strip) = 0;
virtual void paintOverlay(QPainter &p);
virtual void headGrabChanged(bool grabbed);
virtual void visibleRangeChanged();
void paintEvent(QPaintEvent *e) override;
void mousePressEvent(QMouseEvent *e) override;
void mouseMoveEvent(QMouseEvent *e) override;
void mouseReleaseEvent(QMouseEvent *e) override;
void wheelEvent(QWheelEvent *e) override;
void leaveEventHook(QEvent *e) override;
bool eventHook(QEvent *e) override;
private:
enum class Grab {
None,
Left,
Right,
Head,
Window,
Scroll,
Hint,
Label,
};
struct DurationLabel {
QString text;
QRect rect;
bool sizeShown = false;
};
[[nodiscard]] QRect labelRect() const;
[[nodiscard]] DurationLabel durationLabel() const;
[[nodiscard]] QRect durationHitRect() const;
[[nodiscard]] QRect durationFieldRect() const;
[[nodiscard]] QString durationEditText() const;
void updateDurationFieldGeometry();
void editDuration();
void finishDurationEdit(bool apply, bool restoreFocus);
void applyDurationText(const QString &text);
[[nodiscard]] crl::time minSelection() const;
void moveWindowTo(crl::time center);
[[nodiscard]] Grab grabAt(
QPoint position,
Qt::KeyboardModifiers modifiers) const;
[[nodiscard]] float64 maxZoom() const;
bool setVisibleRange(float64 zoom, float64 from);
void zoomBy(float64 factor, int anchorX);
bool scrollBy(float64 pixels);
void updateEdgeScroll(QPoint position);
bool edgeScrollStep(crl::time now);
[[nodiscard]] bool grabClamped(bool forward) const;
[[nodiscard]] bool selectionHiddenLeft() const;
[[nodiscard]] bool selectionHiddenRight() const;
[[nodiscard]] QRect hintRect(bool left) const;
void updateHints();
void scrollToSelection();
[[nodiscard]] bool grabMovesSelection() const;
void applyGrab(QPoint position);
void releaseGrab();
void setCover(crl::time cover, bool notify);
void updateCursor(Grab grab);
void paintSelection(QPainter &p, const QRect &strip);
void paintOverview(QPainter &p, const QRect &strip);
void paintHints(QPainter &p);
void paintHead(QPainter &p, const QRect &strip);
void paintDuration(QPainter &p);
const crl::time _duration = 0;
const crl::time _maxDuration = 0;
const crl::time _minDuration = 0;
const bool _trimOnly = false;
crl::time _from = 0;
crl::time _till = 0;
crl::time _cover = 0;
// Negative means nothing played yet; zero is a real position.
crl::time _playback = -1;
float64 _zoom = 1.;
float64 _visibleFrom = 0.;
QString _sizeLabel;
int _labelWidth = 0;
int _durationFieldWidth = 0;
base::unique_qptr<Ui::MaskedInputField> _durationField;
QPointer<QWidget> _durationFocusReturn;
Grab _grab = Grab::None;
Qt::MouseButton _grabButton = Qt::NoButton;
int _grabShift = 0;
QPoint _dragPosition;
int _edgeOvershoot = 0;
crl::time _edgeScrollLast = 0;
Ui::Animations::Basic _edgeScrollAnimation;
Ui::ScrollDirectionLock _wheelDirectionLock;
bool _hintLeftShown = false;
bool _hintRightShown = false;
bool _hintGrabLeft = false;
Ui::Animations::Simple _hintLeft;
Ui::Animations::Simple _hintRight;
Ui::Animations::Simple _scrollAnimation;
rpl::event_stream<crl::time> _trimChanges;
rpl::event_stream<crl::time> _coverChanges;
rpl::event_stream<bool> _draggingChanges;
};
} // namespace Editor