243 lines
6.3 KiB
C++
243 lines
6.3 KiB
C++
#pragma once
|
|
#include <QEvent>
|
|
#include <QGraphicsDropShadowEffect>
|
|
#include <QMap>
|
|
#include <QMouseEvent>
|
|
#include <QPainter>
|
|
#include <QPainterPath>
|
|
#include <QVector>
|
|
#include <QWidget>
|
|
#include <optional>
|
|
#include <QLineEdit>
|
|
#include <QPainter>
|
|
#include <QApplication>
|
|
#include <QProxyStyle>
|
|
#include <QMainWindow>
|
|
#include <QDebug>
|
|
#include <QStyledItemDelegate>
|
|
|
|
enum class Layout_Item_Type {
|
|
Fixed,
|
|
Expand
|
|
};
|
|
|
|
enum class Layout_Item_Type2 {
|
|
Fixed,
|
|
Expand
|
|
};
|
|
|
|
// 用于线性布局的元素
|
|
struct Layout_Info {
|
|
Layout_Info() = default;
|
|
|
|
Layout_Item_Type main_type{};
|
|
Layout_Item_Type2 second_type{};
|
|
|
|
Layout_Info(int key, Layout_Item_Type main_type, Layout_Item_Type2 second_type, int main_value, int second_value) :
|
|
main_type(main_type),
|
|
second_type(second_type)
|
|
{
|
|
this->key = key;
|
|
if (main_type == Layout_Item_Type::Fixed) {
|
|
len =main_value;
|
|
} else {
|
|
weight = main_value;
|
|
}
|
|
second_len = second_value;
|
|
}
|
|
|
|
|
|
int len{}; // 线性布局主要位置
|
|
int second_len{}; // 线性布局次要位置
|
|
|
|
int weight{}; // 主要位置权重布局
|
|
bool hide = false;
|
|
int key{};
|
|
};
|
|
|
|
struct Layout {
|
|
int prefix = 8, suffix = 8;
|
|
int space = 8;
|
|
int second_prefix = 8, second_suffix = 8;
|
|
QVector<Layout_Info> infos;
|
|
enum Type {
|
|
Prefix_Space,
|
|
Surfix_Space,
|
|
Center_Space
|
|
};
|
|
void set_margin(int margin){
|
|
prefix = margin;
|
|
suffix = margin;
|
|
second_prefix = margin;
|
|
second_suffix = margin;
|
|
}
|
|
Type main_type = Prefix_Space;
|
|
Type second_type = Prefix_Space;
|
|
typedef QFlags<Type> Alignment;
|
|
|
|
struct Pos {
|
|
int start;
|
|
int len;
|
|
int second_start;
|
|
int second_len;
|
|
QRect h_rect() {
|
|
return {start, second_start, len, second_len};
|
|
}
|
|
QRect v_rect() {
|
|
return {second_start, start, second_len, len};
|
|
}
|
|
};
|
|
QMap<int, Pos> cache;
|
|
std::optional<Pos> get(int key) {
|
|
auto iter = cache.find(key);
|
|
if (iter == cache.end()) {
|
|
return std::nullopt;
|
|
}
|
|
return *iter;
|
|
}
|
|
void cacl(int len, int second_len) {
|
|
QVector<Pos> ret(infos.size());
|
|
int total_fixed_pixel_size = 0;
|
|
int total_weight = 0;
|
|
int show_size = 0;
|
|
int n = infos.size();
|
|
for (int i = 0; i < n; ++i) {
|
|
auto& info = infos[i];
|
|
if (info.hide) {
|
|
continue;
|
|
}
|
|
if (info.main_type == Layout_Item_Type::Fixed) {
|
|
total_fixed_pixel_size += info.len;
|
|
}
|
|
if (info.main_type == Layout_Item_Type::Expand) {
|
|
total_weight += info.weight;
|
|
}
|
|
show_size++;
|
|
}
|
|
int show_width = total_fixed_pixel_size + (show_size - 1) * space;
|
|
int remain = len - show_width - (prefix + suffix);
|
|
int main_cur_pos = 0;
|
|
if (main_type == Type::Prefix_Space) {
|
|
main_cur_pos = prefix;
|
|
}
|
|
if (main_type == Type::Center_Space) {
|
|
main_cur_pos = (len - show_width)/2;
|
|
}
|
|
if (main_type == Type::Surfix_Space) {
|
|
main_cur_pos = len - show_width - suffix;
|
|
}
|
|
|
|
for (int i = 0; i < n; ++i) {
|
|
auto& info = infos[i];
|
|
if (info.hide) continue;
|
|
auto& pos = ret[i];
|
|
int cur_len = info.main_type == Layout_Item_Type::Fixed ? info.len :
|
|
static_cast<int>((double)remain * (double)info.weight/(double)total_weight);
|
|
pos.start = main_cur_pos;
|
|
pos.len = cur_len;
|
|
|
|
int info_second_len{};
|
|
if (info.second_type == Layout_Item_Type2::Fixed) {
|
|
info_second_len = info.second_len;
|
|
}
|
|
if (info.second_type == Layout_Item_Type2::Expand) {
|
|
info_second_len = second_len - second_prefix - second_suffix;
|
|
}
|
|
if (second_type == Type::Prefix_Space)
|
|
{
|
|
pos.second_len = second_prefix;
|
|
}
|
|
if (second_type == Type::Center_Space)
|
|
{
|
|
pos.second_start = (second_len - info_second_len) /2;
|
|
}
|
|
if (second_type == Type::Surfix_Space)
|
|
{
|
|
pos.second_start = second_len - info_second_len- second_suffix;
|
|
}
|
|
pos.second_len = info_second_len;
|
|
main_cur_pos += space + cur_len;
|
|
}
|
|
cache.clear();
|
|
for (int i = 0; i < n; ++i)
|
|
{
|
|
auto key = infos[i].key;
|
|
cache[key] = ret[i];
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
|
|
|
|
enum class Event_Type {
|
|
refresh,
|
|
Nothing
|
|
};
|
|
|
|
struct PaintAble {
|
|
PaintAble() = default;
|
|
virtual QSize sizeHint() const {
|
|
return {24, 24};
|
|
}
|
|
virtual ~PaintAble() = default;
|
|
virtual void paint(QPainter* painter, QRect rect) = 0;
|
|
// 鼠标操作
|
|
virtual Event_Type mouse_event(QEvent::Type t, QMouseEvent* e) {
|
|
return Event_Type::Nothing;
|
|
}
|
|
virtual Event_Type resize_event(QResizeEvent* e) {
|
|
return Event_Type::Nothing;
|
|
}
|
|
virtual Event_Type event(QEvent::Type t, QEvent* e) {
|
|
if (t == QEvent::Resize) {
|
|
return resize_event(dynamic_cast<QResizeEvent*>(e));
|
|
}
|
|
if (
|
|
t == QEvent::MouseButtonPress ||
|
|
t == QEvent::MouseButtonRelease ||
|
|
t == QEvent::MouseMove ||
|
|
t == QEvent::MouseButtonDblClick
|
|
) {
|
|
return mouse_event(t, dynamic_cast<QMouseEvent*>(e));
|
|
}
|
|
return Event_Type::Nothing;
|
|
}
|
|
bool show = true;
|
|
};
|
|
|
|
|
|
|
|
struct Base : QWidget {
|
|
QVector<PaintAble*> paintAbles;
|
|
void paintEvent(QPaintEvent* event) override {
|
|
QPainter painter(this);
|
|
painter.setRenderHint(QPainter::Antialiasing);
|
|
QRect rect = event->rect();
|
|
for (auto paintAble : paintAbles) {
|
|
if (paintAble->show) {
|
|
paintAble->paint(&painter, rect);
|
|
}
|
|
}
|
|
painter.end();
|
|
}
|
|
|
|
bool event(QEvent* e) override {
|
|
auto t = e->type();
|
|
for(PaintAble* paintAble : paintAbles){
|
|
Event_Type r = paintAble->event(t, e);
|
|
if (r == Event_Type::refresh) {
|
|
update();
|
|
}
|
|
}
|
|
return QWidget::event(e);
|
|
}
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|