Files
envi-code/SourceCode/Code2026/inc/makeCADTable.h
T
2026-09-28 15:28:50 +08:00

414 lines
9.8 KiB
C++

#pragma once
#ifdef EARTHWORM_EXPORT
#define DLLIMPEXP __declspec(dllexport)
#else
#define DLLIMPEXP __declspec(dllimport)
#endif
#include "dbtable.h"
#include "dbTableStyle.h "
#include <vector>
class DLLIMPEXP MKTABLE
{
public:
typedef std::vector<CString> RowData;
typedef std::vector<RowData> TableData;
public:
// 查找 AcDbTableStyle ,不存在则创建默认样式
static AcDbObjectId getTableStyle(LPCTSTR pszTSName);
// 查找 AcDbTextStyleTableRecord ,不存在则创建默认样式
static AcDbObjectId getTextStyle(LPCTSTR pszTSName);
// 查找 AcDbLinetypeTableRecord ,不存在则创建默认样式
static AcDbObjectId getLinetype(LPCTSTR pszLinetypeName);
// 取 listCtrl 中 idxs 指定的列,按顺序提取数据
static bool extractDatasFromListCtrl(CListCtrl &listCtrl
, std::vector<TableData> &outDatas
, RowData &headers
, const std::vector<int> &idxs
, const int &maxRow);
// 通过界面选择 listCtrl 中的列,并返回所选列的索引,包含顺序
static void selectColumnsFromListCtrl(CHeaderCtrl &headerCtrl
, std::vector<int> &idxs
, double &dPScale
, CString &sTemplate);
// 自动根据表格内容调整表格大小
static void autoSizeTable(AcDbTable *pTable);
// 获得表格模板列表
static void getTableTemplateList(std::vector<CString> &outTemplates);
public:
// 针对数据保存在CListCtrl中的表格,生成 AcDbTable
static bool makeTable(CListCtrl &listCtrl, LPCTSTR pszTitle, const int &maxRow);
};
#define _DEFINE_(type, name)\
void set##name(const type &val)\
{\
m_##name = val;\
m_bUse##name = true;\
}\
type m_##name;\
bool m_bUse##name
#define _DEFINE_LINETYPE_PROPERTY_(name, linetype)\
void set##name(const CellGridLineTypeProperty &val)\
{\
m_##name = val;\
m_bUse##name = true;\
}\
CellGridLineTypeProperty m_##name;\
bool m_bUse##name
#define APPLY_MARGIN(v)\
if (m_bUse##v)\
{\
pTS->setMargin(AcDb::kCellMargin##v, m_##v*dPScale, pszCellStyle);\
}
#define APPLY_GRIDLINE_PROPERTY(v)\
if (m_bUse##v)\
{\
pTb->setGrid##v(nRow, nCol, m_type, m_##v);\
}
#define APPLY_GRIDLINE_TYPE(v)\
for (size_t i = 0; i < m_##v.size(); ++i)\
{\
m_##v[i].apply2Table(pTb);\
}\
#define APPLY_CELL_STYLE(v)\
if (m_bUse##v)\
{\
pTS->set##v(m_##v, m_sName);\
}
class MKTABLE;
namespace TABLE
{
struct CellMergeRange
{
int m_maxRow, m_minRow, m_maxCol, m_minCol;
CellMergeRange(): m_maxRow(-1), m_minRow(-1), m_maxCol(-1), m_minCol(-1) {}
CellMergeRange(const CellMergeRange &mg): m_maxRow(mg.m_maxRow)
, m_minRow(mg.m_minRow)
, m_maxCol(mg.m_maxCol)
, m_minCol(mg.m_minCol) { }
CellMergeRange(const int &minRow
, const int &maxRow
, const int &minCol
, const int &maxCol)
: m_maxRow(maxRow)
, m_minRow(minRow)
, m_maxCol(maxCol)
, m_minCol(minCol) { }
CellMergeRange& operator=(const CellMergeRange &mg)
{
if (this != &mg)
{
m_maxRow = mg.m_maxRow;
m_minRow = mg.m_minRow;
m_maxCol = mg.m_maxCol;
m_minCol = mg.m_minCol;
}
return *this;
}
bool vaild(const int &nRow, const int &nCol)
{
// 负数表示从后往前计数,先计算正确位置
if (m_minRow < 0) m_minRow += nRow;
if (m_maxRow < 0) m_maxRow += nRow;
if (m_minCol < 0) m_minCol += nCol;
if (m_maxCol < 0) m_maxCol += nCol;
// 边缘保护调整
// 最小行/列 小于0,调整为0,即第一行
if (m_minRow < 0) m_minRow = 0;
if (m_minCol < 0) m_minCol = 0;
// 最大行/列 大于总行/列数,调整为总行/列数-1,即最后一行
if (m_maxRow >= nRow) m_maxRow = nRow - 1;
if (m_maxCol >= nRow) m_maxCol = nCol - 1;
// 最小行/列大于总行/列数
if (m_minRow > nRow || m_minCol > nCol) return false;
// 最大行/列 小于0
if (m_maxRow < 0 || m_maxCol < 0) return false;
// 最小行/列 大于 最大行/列
if (m_minRow > m_maxRow || m_minCol > m_maxCol) return false;
return true;
}
void apply2Table(AcDbTable *pTb)
{
if (vaild(pTb->numRows(), pTb->numColumns()))
pTb->mergeCells(m_minRow, m_maxRow, m_minCol, m_maxCol);
}
};
typedef std::vector<CellMergeRange> CellMerges;
struct CellMargin
{
_DEFINE_(double, Left);
_DEFINE_(double, Right);
_DEFINE_(double, Top);
_DEFINE_(double, Bottom);
_DEFINE_(double, HorzSpacing);
_DEFINE_(double, VertSpacing);
CellMargin(): m_bUseLeft(false)
, m_bUseRight(false)
, m_bUseTop(false)
, m_bUseBottom(false)
, m_bUseHorzSpacing(false)
, m_bUseVertSpacing(false) { }
void apply2TableStyle(AcDbTableStyle *pTS, LPCTSTR pszCellStyle, const double &dPScale)
{
APPLY_MARGIN(Left);
APPLY_MARGIN(Right);
APPLY_MARGIN(Top);
APPLY_MARGIN(Bottom);
APPLY_MARGIN(HorzSpacing);
APPLY_MARGIN(VertSpacing);
}
};
struct GridLineTypeProperty
{
int m_minRow, m_minCol;
int m_maxRow, m_maxCol;
double m_dPScale;
AcDb::GridLineType m_type;
_DEFINE_(AcDb::GridLineStyle, LineStyle);
_DEFINE_(AcDb::LineWeight, LineWeight);
_DEFINE_(CString, Linetype);
_DEFINE_(int, Color);
_DEFINE_(AcDb::Visibility, Visibility);
_DEFINE_(double, DoubleLineSpacing);
GridLineTypeProperty(AcDb::GridLineType type
, const int &minRow
, const int &maxRow
, const int &minCol
, const int &maxCol
, const double &dps )
: m_type(type)
, m_dPScale(dps)
, m_minRow(minRow)
, m_maxRow(maxRow)
, m_minCol(minCol)
, m_maxCol(maxCol)
, m_bUseLinetype(false)
, m_bUseColor(false)
, m_bUseLineStyle(false)
, m_bUseLineWeight(false)
, m_bUseVisibility(false)
, m_bUseDoubleLineSpacing(false) { }
void apply2Table(AcDbTable *pTb) const
{
CellMergeRange tempRange(m_minRow, m_maxRow, m_minCol, m_maxCol);
// 先调整范围合法性
if (!tempRange.vaild(pTb->numRows(), pTb->numColumns())) return;
int minRow = tempRange.m_minRow;
int maxRow = tempRange.m_maxRow;
int minCol = tempRange.m_minCol;
int maxCol = tempRange.m_maxCol;
for (int nRow(minRow); nRow <= maxRow; ++nRow)
{
for (int nCol(minCol); nCol <= maxCol; ++nCol)
{
APPLY_GRIDLINE_PROPERTY(LineStyle);
APPLY_GRIDLINE_PROPERTY(LineWeight);
APPLY_GRIDLINE_PROPERTY(Visibility);
if (m_bUseDoubleLineSpacing)
{
pTb->setGridDoubleLineSpacing(nRow
, nCol
, m_type
, m_DoubleLineSpacing * m_dPScale);
}
if (m_bUseColor)
{
AcCmColor clr;
clr.setColorIndex(m_Color);
pTb->setGridColor(m_type, nRow, nCol, clr);
}
if (m_bUseLinetype)
{
AcDbObjectId id(MKTABLE::getTextStyle(m_Linetype));
if (id.isValid())
pTb->setGridLinetype(nRow, nCol, m_type, id);
}
}
}
}
};
typedef std::vector<GridLineTypeProperty> GridLineTypePropertys;
struct GridLineType
{
_DEFINE_(GridLineTypePropertys, HorzTop);
_DEFINE_(GridLineTypePropertys, HorzInside);
_DEFINE_(GridLineTypePropertys, HorzBottom);
_DEFINE_(GridLineTypePropertys, VertLeft);
_DEFINE_(GridLineTypePropertys, VertInside);
_DEFINE_(GridLineTypePropertys, VertRight);
_DEFINE_(GridLineTypePropertys, HorzGridLineTypes);
_DEFINE_(GridLineTypePropertys, VertGridLineTypes);
_DEFINE_(GridLineTypePropertys, OuterGridLineTypes);
_DEFINE_(GridLineTypePropertys, InnerGridLineTypes);
_DEFINE_(GridLineTypePropertys, AllGridLineTypes);
GridLineType(){ }
void apply2Table(AcDbTable *pTb) const
{
APPLY_GRIDLINE_TYPE(HorzTop);
APPLY_GRIDLINE_TYPE(HorzInside);
APPLY_GRIDLINE_TYPE(HorzBottom);
APPLY_GRIDLINE_TYPE(VertLeft);
APPLY_GRIDLINE_TYPE(VertInside);
APPLY_GRIDLINE_TYPE(VertRight);
APPLY_GRIDLINE_TYPE(HorzGridLineTypes);
APPLY_GRIDLINE_TYPE(VertGridLineTypes);
APPLY_GRIDLINE_TYPE(OuterGridLineTypes);
APPLY_GRIDLINE_TYPE(InnerGridLineTypes);
APPLY_GRIDLINE_TYPE(AllGridLineTypes);
}
};
struct CellStyle
{
CString m_sName;
_DEFINE_(CString, TextStyle);
_DEFINE_(double, TextHeight);
_DEFINE_(double, Rotation);
_DEFINE_(int, Color);
_DEFINE_(int, BackgroundColor);
_DEFINE_(AcDb::CellAlignment, Alignment);
_DEFINE_(CellMargin, Margin);
_DEFINE_(bool, enableMergeAll);
CellStyle(): m_sName(_T(""))
, m_bUseColor(false)
, m_bUseBackgroundColor(false)
, m_bUseTextStyle(false)
, m_bUseTextHeight(false)
, m_bUseRotation(false)
, m_bUseMargin(false)
, m_bUseenableMergeAll(false)
, m_bUseAlignment(false) { }
void apply2CellStyle(AcDbTableStyle *pTS, const double &dPScale)
{
AcStringArray cellnames;
pTS->getCellStyles(cellnames);
if (cellnames.find((LPCTSTR)m_sName) == -1)
{
if (pTS->createCellStyle(m_sName) != Acad::eOk)
return;
}
APPLY_CELL_STYLE(Alignment);
APPLY_CELL_STYLE(Rotation);
if (m_bUseTextHeight)
{
pTS->setTextHeight(m_TextHeight * dPScale, m_sName);
}
if (m_bUseColor)
{
AcCmColor clr;
clr.setColorIndex(m_Color);
pTS->setColor(clr, m_sName);
}
if (m_bUseBackgroundColor)
{
AcCmColor clr;
clr.setColorIndex(m_BackgroundColor);
pTS->setBackgroundColor(clr, m_sName);
}
if (m_bUseTextStyle)
{
AcDbObjectId tsId = MKTABLE::getTextStyle(m_TextStyle);
if (tsId.isValid())
pTS->setTextStyle(tsId, m_sName);
}
if (m_bUseenableMergeAll)
pTS->enableMergeAll(m_enableMergeAll, m_sName);
if (m_bUseMargin)
{
m_Margin.apply2TableStyle(pTS, m_sName, dPScale);
}
}
};
typedef std::map<CString, CellStyle> CellStyles;
struct Cell
{
int row;
int col;
CString text;
CString style;
void apply2Table(AcDbTable *pTb) const
{
if (!pTb) return;
pTb->setTextString(row, col, text);
if (!style.IsEmpty())
pTb->setCellStyle(row, col, style);
}
};
typedef std::vector<Cell> Cells, CellRowData;
typedef std::vector<Cells> CellTableData;
struct TableStyle
{
CString m_sName;
std::map<CString, CellStyle> m_cellStyles;
};
typedef std::map<CString, TableStyle> TableStyles;
struct DataContent
{
// 默认单元格样式,一定要设置,只能是_TITLE,_DATA,_HEADER
// 因为这三种样式是 AcDbTableStyle 自带并且无法删除的
CString m_defCellStyle;
CellTableData m_tableData;
DataContent(LPCTSTR def): m_defCellStyle(def) {}
};
typedef std::map<CString, DataContent> DataContents;
}