Files
OmaPhoto/src/UI/TransformInspector.h
T

91 lines
2.9 KiB
C++

#pragma once
#include "Document/EditorSession.h"
#include "UI/ToolHeaderStyle.h"
#include <QCheckBox>
#include <QComboBox>
#include <QGraphicsOpacityEffect>
#include <QLineEdit>
#include <QPropertyAnimation>
#include <QPushButton>
#include <QScrollArea>
#include <QToolButton>
#include <functional>
class NumericScrub;
// A labelled number, typed at once, stepped by arrows.
class TransformValueField : public QWidget {
Q_OBJECT
public:
// The label scrubs within low and high, in whole steps.
TransformValueField(const QString &label, const QString &suffix, double low, double high, EditorSession &session,
std::function<void()> finish, std::function<void(double)> change, QWidget *parent = nullptr);
// Shown when the field is not being edited.
void sync(double value);
// Swift's `.id` drops a scrub under way with its layer.
void endScrub();
// No idle zeros on a whole number, two decimals otherwise.
static QString formatted(double value);
QLineEdit *const field;
protected:
bool eventFilter(QObject *watched, QEvent *event) override;
private:
EditorSession &m_session;
// Done with its value: a scrub let go, or left.
const std::function<void()> m_finish;
const std::function<void(double)> m_change;
NumericScrub *m_scrub = nullptr;
double m_value = 0;
// A menu or popup borrows the focus: the typing stays.
bool m_borrowed = false;
};
// The Move tool's bar: numbers, settings, Apply and Cancel.
class TransformInspector : public ToolHeaderBar {
Q_OBJECT
public:
explicit TransformInspector(EditorSession &session, QWidget *parent = nullptr);
protected:
// Return applies and Escape cancels outside the fields.
void keyPressEvent(QKeyEvent *event) override;
void changeEvent(QEvent *event) override;
private:
void applyLockIcon();
LayerTransform value() const;
QSizeF pixelSize() const;
void change(const std::function<void(LayerTransform &)> &update);
// What the fields changed applies, one step.
void finish();
// Swift's `resize`; the name would hide QWidget's.
void resizeBox(double number, bool width);
void synchronize();
EditorSession &m_session;
// The layer the fields were built for, as Swift's `.id`.
std::optional<QUuid> m_layerID;
QCheckBox *const m_autoSelect;
QCheckBox *const m_showControls;
QScrollArea *const m_fields;
TransformValueField *const m_x;
TransformValueField *const m_y;
TransformValueField *const m_width;
TransformValueField *const m_height;
QToolButton *const m_lock;
TransformValueField *const m_scale;
TransformValueField *const m_rotation;
QComboBox *const m_sampling;
QPushButton *const m_cancel;
QPushButton *const m_apply;
// Cancel and Apply, seen only while an edit waits.
QWidget *const m_pendingButtons;
QGraphicsOpacityEffect *const m_fade;
QPropertyAnimation *const m_fadeIn;
bool m_pending = false;
};