Files
EzUI/include/EzUI/TableView.h
2026-01-29 09:45:03 +08:00

496 lines
14 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
#include "Control.h"
#include "Label.h"
#include "TextBox.h"
#include "CheckBox.h"
#include "ComboBox.h"
#include "VScrollBar.h"
#include "HScrollBar.h"
#include <functional>
#include <algorithm>
namespace ezui {
// 第一列类型枚举
enum class FirstColumnType {
TextBox, // 空白文本框(默认)
Index, // 不可编辑的序号从1开始
CheckBox // 选择框
};
// 单元格类型枚举
enum class CellType {
TextBox, // 文本框(默认)
CheckBox, // 选择框
ComboBox, // 下拉选择框
ReadOnly // 不可编辑(可选中复制但不能修改)
};
// 边框类型(复用框架的 StrokeStyle
// StrokeStyle::None - 无边框
// StrokeStyle::Solid - 实线
// StrokeStyle::Dash - 虚线
// 排序方向
enum class SortOrder {
None, // 未排序
Ascending, // 升序
Descending // 降序
};
// 单元格独立样式(用于单独设置某个单元格的样式)
struct CellStyle {
Color BorderColor;
StrokeStyle BorderStyle = StrokeStyle::None;
Color BackColor;
Color ForeColor;
TextAlign Align = TextAlign::TopLeft;
bool HasBorderColor = false;
bool HasBorderStyle = false;
bool HasBackColor = false;
bool HasForeColor = false;
bool HasTextAlign = false;
void SetBorderColor(const Color& color) {
BorderColor = color;
HasBorderColor = true;
}
void SetBorderStyle(StrokeStyle style) {
BorderStyle = style;
HasBorderStyle = true;
}
void SetBackColor(const Color& color) {
BackColor = color;
HasBackColor = true;
}
void SetForeColor(const Color& color) {
ForeColor = color;
HasForeColor = true;
}
void SetTextAlign(ezui::TextAlign align) {
Align = align;
HasTextAlign = true;
}
void Reset() {
HasBorderColor = false;
HasBorderStyle = false;
HasBackColor = false;
HasForeColor = false;
HasTextAlign = false;
}
};
// 单元格数据
struct CellData {
UIString Text; // 单元格文本内容
bool Checked = false; // 用于 CheckBox 类型
int ComboIndex = -1; // 用于 ComboBox 类型,选中的索引
CellStyle Style; // 单元格独立样式
};
// 列信息
struct ColumnInfo {
UIString HeaderText; // 表头文字
int Width = 100; // 列宽
CellType Type = CellType::TextBox; // 单元格类型
std::vector<UIString> ComboItems; // 下拉选项(仅 ComboBox 类型有效)
SortOrder CurrentSort = SortOrder::None; // 当前排序状态
TextAlign CellTextAlign = TextAlign::TopLeft; // 该列的默认对齐方式
};
class UI_EXPORT TableView : public Control {
private:
// 滚动条
VScrollBar m_vScrollBar;
HScrollBar m_hScrollBar;
// 数据存储
std::vector<ColumnInfo> m_columns; // 列信息
std::vector<std::vector<CellData>> m_data; // 二维数据 [row][col]
std::vector<int> m_rowHeights; // 每行高度
std::vector<bool> m_rowChecked; // 每行的选中状态第一列为CheckBox时使用
// 第一列配置
FirstColumnType m_firstColumnType = FirstColumnType::TextBox;
int m_firstColumnWidth = 50; // 第一列宽度
// 表头配置
int m_headerHeight = 30; // 表头高度
bool m_headerSelectAll = false; // 表头全选状态
// 默认行高
int m_defaultRowHeight = 30;
// 统一单元格样式
int m_cellBorderSize = 1;
StrokeStyle m_cellBorderStyle = StrokeStyle::Solid;
Color m_cellBorderColor = Color::LightGray;
Color m_cellBackColor = Color::White;
Color m_cellForeColor = Color::Black;
int m_cellFontSize = 14;
std::wstring m_cellFontFamily = L"Microsoft YaHei";
TextAlign m_cellTextAlign = TextAlign::TopLeft; // 默认对齐方式
std::vector<TextAlign> m_rowTextAlign; // 每行的对齐方式(未设置时使用默认值)
// 表头样式
Color m_headerBackColor = Color(0xFFE0E0E0);
Color m_headerForeColor = Color::Black;
// 滚动偏移
int m_scrollOffsetX = 0;
int m_scrollOffsetY = 0;
// 内容大小缓存供GetContentSize使用
mutable Size m_contentSize;
// 编辑状态
bool m_editing = false;
int m_editRow = -1;
int m_editCol = -1;
TextBox* m_editBox = nullptr;
ComboBox* m_editCombo = nullptr;
CheckBox* m_editCheck = nullptr;
// 列宽拖动
bool m_draggingColumn = false;
int m_dragColumnIndex = -1;
int m_dragStartX = 0;
int m_dragStartWidth = 0;
// 排序
int m_sortColumnIndex = -1;
// 鼠标悬停
int m_hoverRow = -1;
int m_hoverCol = -1;
// 双击检测
ULONGLONG m_lastClickTime = 0;
int m_lastClickRow = -1;
int m_lastClickCol = -1;
// 选中行非CheckBox模式下通过单击第一列选中的行
int m_selectedRow = -1;
// 编辑前的原始值(用于编辑完成回调)
UIString m_editOriginalValue;
private:
void Init();
// 计算总内容宽度
int GetContentWidth() const;
// 计算总内容高度
int GetContentHeight() const;
// 获取列起始X坐标考虑滚动偏移
int GetColumnX(int colIndex) const;
// 获取行起始Y坐标考虑滚动偏移
int GetRowY(int rowIndex) const;
// 根据坐标获取单元格位置
bool HitTestCell(const Point& pt, int* outRow, int* outCol) const;
// 根据坐标检测是否在列边界上(用于拖动调整列宽)
int HitTestColumnBorder(const Point& pt) const;
// 检测是否点击在垂直滚动条上
bool HitTestVScrollBar(const Point& pt);
// 检测是否点击在水平滚动条上
bool HitTestHScrollBar(const Point& pt);
// 绘制表头
void DrawHeader(PaintEventArgs& args);
// 绘制单元格
void DrawCells(PaintEventArgs& args);
// 绘制单个单元格
void DrawCell(PaintEventArgs& args, int row, int col, const Rect& cellRect);
// 绘制第一列
void DrawFirstColumn(PaintEventArgs& args, int row, const Rect& cellRect);
// 开始编辑单元格
void BeginEdit(int row, int col);
// 结束编辑
void EndEdit(bool save = true);
// 更新行高(根据内容)
void UpdateRowHeight(int row);
// 计算文本需要的行数
int CalculateTextLines(const UIString& text, int width) const;
// 刷新滚动条
void RefreshScrollBars();
// 滚动偏移处理
void OffsetX(int offset);
void OffsetY(int offset);
// 执行排序
void DoSort(int colIndex);
protected:
virtual void OnPaint(PaintEventArgs& args) override;
virtual void OnChildPaint(PaintEventArgs& args) override;
virtual void OnLayout() override;
virtual void OnMouseMove(const MouseEventArgs& args) override;
virtual void OnMouseDown(const MouseEventArgs& args) override;
virtual void OnMouseUp(const MouseEventArgs& args) override;
virtual void OnMouseDoubleClick(const MouseEventArgs& args) override;
virtual void OnMouseWheel(const MouseEventArgs& args) override;
virtual void OnMouseLeave(const MouseEventArgs& args) override;
virtual void OnSize(const SizeEventArgs& args) override;
virtual void OnKeyDown(const KeyboardEventArgs& args) override;
virtual void OnKeyChar(const KeyboardEventArgs& args) override;
virtual const Size& GetContentSize() override;
public:
// 选中行背景色当第一列为CheckBox且被选中时使用或者单击选中行时使用
Color SelectedRowBackColor = Color(0xFFADD8E6); // 浅蓝色
/*
table->CellValueChanged = [](int row, int col, const UIString& value) {
// 处理内容变化
};
*/
// 单元格内容变化回调(内容变化时立即触发)
// 参数: row, col, newValue
std::function<void(int, int, const UIString&)> CellValueChanged = nullptr;
/*
table->CellEditFinished = [](int row, int col, const UIString& oldValue, const UIString& newValue) {
// 处理内容变化
};
*/
// 单元格编辑完成回调编辑结束时触发比如TextBox失去焦点或按Enter时
// 参数: row, col, oldValue, newValue
std::function<void(int, int, const UIString&, const UIString&)> CellEditFinished = nullptr;
/*
tableView->RightClick= [tableView](int row, int col) {
// 处理内容变化
};
*/
// 鼠标右键单击回调
// 参数: row, col (row=-1 表示点击在表头col=-1 表示点击在第一列)
std::function<void(int, int)> RightClick = nullptr;
public:
TableView(Object* parentObject = nullptr);
virtual ~TableView();
// ============ 表头设置 ============
// 设置表头(传入表头名数组)
void SetHeaders(const std::vector<UIString>& headers);
// 获取表头数量(不包含第一列)
int GetColumnCount() const;
// 设置表头高度
void SetHeaderHeight(int height);
// 获取表头高度
int GetHeaderHeight() const;
// ============ 第一列设置 ============
// 设置第一列类型
void SetFirstColumnType(FirstColumnType type);
// 获取第一列类型
FirstColumnType GetFirstColumnType() const;
// 设置第一列宽度
void SetFirstColumnWidth(int width);
// 获取第一列宽度
int GetFirstColumnWidth() const;
// ============ 列设置 ============
// 设置某列宽度
void SetColumnWidth(int colIndex, int width);
// 获取某列宽度
int GetColumnWidth(int colIndex) const;
// 获取所有列宽
const std::vector<int> GetColumnWidths() const;
// 设置某列单元格类型
void SetColumnType(int colIndex, CellType type);
// 获取某列单元格类型
CellType GetColumnType(int colIndex) const;
// 设置某列的下拉选项(仅对 ComboBox 类型有效)
void SetColumnComboItems(int colIndex, const std::vector<UIString>& items);
// ============ 行设置 ============
// 获取行数
int GetRowCount() const;
// 添加行
void AddRow();
// 插入行
void InsertRow(int rowIndex);
// 删除行
void RemoveRow(int rowIndex);
// 清空所有行
void ClearRows();
// 添加列
void AddColumn(const UIString& headerText = L"", int width = 100);
// 插入列
void InsertColumn(int colIndex, const UIString& headerText = L"", int width = 100);
// 删除列
void RemoveColumn(int colIndex);
// 获取行高
int GetRowHeight(int rowIndex) const;
// 获取所有行高
const std::vector<int> GetRowHeights() const;
// 设置默认行高
void SetDefaultRowHeight(int height);
// ============ 数据操作 ============
// 设置单个单元格数据
void SetData(int row, int col, const UIString& value);
// 获取单个单元格数据
UIString GetData(int row, int col) const;
// 设置整行数据
void SetRowData(int row, const std::vector<UIString>& values);
// 获取整行数据
std::vector<UIString> GetRowData(int row) const;
// 获取整列数据
std::vector<UIString> GetColData(int col) const;
// 设置全部数据(二维数组)
void SetAllData(const std::vector<std::vector<UIString>>& data);
// 获取全部数据
std::vector<std::vector<UIString>> GetAllData() const;
// 设置单元格 CheckBox 状态
void SetCellChecked(int row, int col, bool checked);
// 获取单元格 CheckBox 状态
bool GetCellChecked(int row, int col) const;
// 设置单元格 ComboBox 选中索引
void SetCellComboIndex(int row, int col, int index);
// 获取单元格 ComboBox 选中索引
int GetCellComboIndex(int row, int col) const;
// ============ 行选中第一列为CheckBox时 ============
// 设置某行选中状态
void SetRowChecked(int row, bool checked);
// 获取某行选中状态
bool GetRowChecked(int row) const;
// 获取所有选中的行索引
std::vector<int> GetCheckedRows() const;
// 获取当前选中的行非CheckBox模式通过单击第一列选中
int GetSelectedRow() const;
// 设置当前选中的行非CheckBox模式
void SetSelectedRow(int row);
// 清除选中行非CheckBox模式
void ClearSelection();
// 全选
void SelectAll();
// 取消全选
void DeselectAll();
// ============ 样式设置 ============
// 设置统一单元格样式
void SetCellBorderSize(int size);
void SetCellBorderStyle(StrokeStyle style);
void SetCellBorderColor(const Color& color);
void SetCellBackColor(const Color& color);
void SetCellForeColor(const Color& color);
void SetCellFontSize(int size);
void SetCellFontFamily(const std::wstring& fontFamily);
// 设置单独单元格样式
void SetCellStyle(int row, int col, const CellStyle& style);
// 获取单独单元格样式
CellStyle GetCellStyle(int row, int col) const;
// 重置单独单元格样式(使用统一样式)
void ResetCellStyle(int row, int col);
// 设置表头样式
void SetHeaderBackColor(const Color& color);
void SetHeaderForeColor(const Color& color);
// ============ 对齐方式设置 ============
// 设置默认对齐方式(影响所有未单独设置对齐方式的单元格)
void SetDefaultTextAlign(TextAlign align);
// 设置某列的对齐方式
void SetColumnTextAlign(int colIndex, TextAlign align);
// 设置某行的对齐方式
void SetRowTextAlign(int rowIndex, TextAlign align);
// 设置单个单元格的对齐方式
void SetCellTextAlign(int row, int col, TextAlign align);
// 获取单元格的对齐方式(考虑优先级:单元格 > 行 > 列 > 默认)
TextAlign GetCellTextAlign(int row, int col) const;
// ============ 鼠标悬停信息 ============
// 获取鼠标当前悬停的行号(-1表示表头或未悬停在任何行
int GetHoverRow() const;
// 获取鼠标当前悬停的列号(-1表示第一列或未悬停在任何列
int GetHoverCol() const;
// 获取鼠标当前悬停的行列号(通过指针返回)
void GetHoverCell(int* outRow, int* outCol) const;
// ============ 滚动条 ============
virtual ScrollBar* GetVScrollBar();
virtual ScrollBar* GetHScrollBar();
// ============ 属性设置XML支持 ============
virtual void SetAttribute(const UIString& key, const UIString& value) override;
};
};