88 lines
3.2 KiB
C++
88 lines
3.2 KiB
C++
#pragma once
|
||
#include <vector>
|
||
|
||
#include <QString>
|
||
#include <QWidget>
|
||
|
||
#include "model/ColorScale.hpp" // core::Rgba
|
||
|
||
namespace geopro::app {
|
||
|
||
// 连续渐变编辑画布(1:1 复刻 colorLevelConfigurator.js):从上到下依次为
|
||
// 顶部留白(40) → 直方图(高100,灰柱) → 间距10 → 色带(高20) → 间距10 →
|
||
// 滑轨黑线 → 手柄(9px方块,落在滑轨上)。
|
||
// 交互:双击滑轨空白加断点(色=该处采样);拖动中间手柄改位置;选中后 Delete/右键删除;
|
||
// 首尾手柄锁定(不可拖/删/选)。断点 pos∈[0,1],导出按 pos 升序。
|
||
class GradientEditWidget : public QWidget {
|
||
Q_OBJECT
|
||
public:
|
||
struct Stop {
|
||
double pos;
|
||
geopro::core::Rgba color;
|
||
};
|
||
|
||
explicit GradientEditWidget(QWidget* parent = nullptr);
|
||
|
||
void setStops(const std::vector<Stop>& stops); // pos 升序,至少 2 个
|
||
std::vector<Stop> stops() const; // 升序导出
|
||
void reverse(); // 反向:保持各 pos 不变,仅反转颜色序列
|
||
|
||
void setMinMax(double minValue, double maxValue); // 直方图域 + 读出域
|
||
void setSamples(std::vector<double> samples); // 直方图样本
|
||
|
||
// 改当前选中手柄颜色(复刻 updateColorById)。无选中则无操作。
|
||
void setSelectedColor(const geopro::core::Rgba& color);
|
||
bool hasSelection() const { return selectedId_ >= 0; }
|
||
|
||
QSize sizeHint() const override { return QSize(560, 220); }
|
||
|
||
signals:
|
||
void changed();
|
||
// 选中/拖动时携带当前手柄信息(复刻 onHandleClick / onHandleMove + getHandleInfo)。
|
||
// colorHex 形如 "#RRGGBB";valueText=值.toFixed(2);percentText="xx.x%"。
|
||
void handleSelected(QString colorHex, QString valueText, QString percentText);
|
||
void selectionCleared(); // 点击空白清除选中
|
||
|
||
protected:
|
||
void paintEvent(QPaintEvent*) override;
|
||
void mousePressEvent(QMouseEvent*) override;
|
||
void mouseMoveEvent(QMouseEvent*) override;
|
||
void mouseDoubleClickEvent(QMouseEvent*) override;
|
||
void mouseReleaseEvent(QMouseEvent*) override;
|
||
void keyPressEvent(QKeyEvent*) override;
|
||
|
||
private:
|
||
struct Node {
|
||
double pos;
|
||
geopro::core::Rgba color;
|
||
int id;
|
||
};
|
||
|
||
int hitHandle(const QPointF& p) const; // 命中手柄 id,否则 -1
|
||
bool isEndpoint(int id) const; // 首尾(按 pos 升序)
|
||
bool isOnSliderLine(const QPointF& p) const; // 落在滑轨线附近
|
||
double posToX(double pos) const; // 手柄左边缘 x
|
||
double xToPos(double x) const;
|
||
geopro::core::Rgba sample(double pos) const; // 色带连续插值取色
|
||
void sortNodes();
|
||
void emitChangedRepaint();
|
||
void emitHandleInfo(const Node& n); // 发选中/拖动信息信号
|
||
|
||
double histTop() const; // 直方图顶 y
|
||
double colorBarTop() const;
|
||
double sliderLineY() const;
|
||
double trackLeft() const; // 轨道左 x = RECT_SIZE
|
||
double trackWidth() const; // 轨道宽 = width - RECT_SIZE*2
|
||
|
||
std::vector<Node> nodes_;
|
||
int nextId_ = 0;
|
||
int selectedId_ = -1;
|
||
bool dragging_ = false;
|
||
|
||
double minValue_ = 0.0;
|
||
double maxValue_ = 100.0;
|
||
std::vector<double> samples_;
|
||
};
|
||
|
||
} // namespace geopro::app
|