// DbTreeView.cpp : implementation file
//
#include "stdafx.h"
#include "minidatabase.h"
#include "DbTreeView.h"
#include "TextView.h"
#include "MainFrm.h"
#include "TableDlg.h"
#include "FieldDlg.h"
#include "KeyDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
const UINT IDC_TREE_CTRL = 1001;
/////////////////////////////////////////////////////////////////////////////
// CDbTreeView
IMPLEMENT_DYNCREATE(CDbTreeView, CView)
CDbTreeView::CDbTreeView()
{
m_pEditMemory = (BYTE *)malloc(EDIT_MEMORY_SIZE);
if (m_pEditMemory)
m_pMemoryEnd = m_pEditMemory + EDIT_MEMORY_SIZE;
else
m_pMemoryEnd = NULL;
// 设置数据库内存
RestartMemory();
// 初始化一个表
init_my_db(&m_hashEditDb, NULL);
}
CDbTreeView::~CDbTreeView()
{
if (m_pEditMemory)
free(m_pEditMemory);
}
void CDbTreeView::RestartMemory()
{
tool_set_nofree_base(m_pEditMemory, m_pMemoryEnd, m_pEditMemory);
}
#define _PM IsPrivateMemory
BOOL CDbTreeView::IsPrivateMemory(void *buff)
{
if (m_pEditMemory)
{
if (buff >= m_pEditMemory && buff < m_pMemoryEnd)
return FALSE;
}
return TRUE;
}
void CDbTreeView::ClearTable(TABLE *table)
{
RECORD *record = table->records;
do
{
if (record == NULL)
break;
RECORD *temp = record;
record = record->next;
if (_PM(temp))
delete temp;
} while (record != table->records);
}
void CDbTreeView::ClearBranchNode(CTreeCtrl &tc, HTREEITEM hti, BOOL bDelPriv)
{
HTREEITEM htiChild = NULL;
while (hti)
{
// 获取子节点
htiChild = tc.GetChildItem(hti);
if (htiChild)
ClearBranchNode(tc, htiChild, bDelPriv);
// 删除当前节点信息
DWORD dwData = tc.GetItemData(hti);
if (dwData > 0)
{
NODE_DATA *nd = (NODE_DATA *)dwData;
switch (nd->type)
{
case DATA_TYPE_TABLE:
if (bDelPriv)
{
TABLE *table = (TABLE *)nd->data;
// 清理表记录内存
ClearTable(table);
// 清理表自身内存
if (_PM(table->name))
delete table->name;
if (_PM(table->fields))
delete table->fields;
if (_PM(table->keys))
delete table->keys;
if (_PM(table))
delete table;
}
break;
case DATA_TYPE_FIELD:
if (bDelPriv)
{
FIELD *f = (FIELD *)nd->data;
if (_PM(f->name))
delete f->name;
if ((f->flags & FF_HAVE_DEFAULT)
&& (f->count > 1)
&& _PM(f->dv_ptr))
delete f->dv_ptr;
}
break;
case DATA_TYPE_KEY:
if (bDelPriv)
{
KEY *k = (KEY *)nd->data;
if (_PM(k->fields))
delete k->fields;
}
break;
}
delete nd;
}
HTREEITEM hDel = hti;
// 获取兄弟节点
hti = tc.GetNextSiblingItem(hti);
// 删除
tc.DeleteItem(hDel);
}
}
void CDbTreeView::ClearTree()
{
CTreeCtrl &tc = m_treeCtrl;
// 递归调用清除所有节点信息
ClearBranchNode(tc, tc.GetRootItem());
tc.DeleteAllItems();
// 隐藏记录视图
CMainFrame *mf = (CMainFrame *)GetParentFrame();
mf->m_pEditDbView[1]->PostMessage(WM_HIDE_GRID, 0, 0);
}
CString GetFieldType(FIELD *f)
{
CString str;
switch (f->type)
{
case FIELD_TYPE_CHAR:
str = _T("CHAR");
break;
case FIELD_TYPE_BYTE:
str = _T("BYTE");
break;
case FIELD_TYPE_SHORT:
str = _T("SHORT");
break;
case FIELD_TYPE_WORD:
str = _T("USHORT");
break;
case FIELD_TYPE_INT:
str = _T("INT");
break;
case FIELD_TYPE_UINT:
str = _T("UINT");
break;
default:
str = _T("UNKNOW");
}
if (f->count > 1)
{
CString strArr;
strArr.Format(_T("(%u)"), f->count);
str += strArr;
}
return str;
}
HTREEITEM CDbTreeView::InsertTreeNode(CTreeCtrl &tc, HTREEITEM htiParent, HTREEITEM htiAfter,
CString strTitle, int iImage, int iSelImage,
NODE_DATA *nd)
{
TV_INSERTSTRUCT newTreeItem;
newTreeItem.hParent = htiParent;
newTreeItem.hInsertAfter = htiAfter;
newTreeItem.item.iImage = iImage;
newTreeItem.item.iSelectedImage = iSelImage;
newTreeItem.item.pszText = (LPSTR)((LPCTSTR)strTitle);
newTreeItem.item.mask = TVIF_TEXT;
if (iImage >= 0)
newTreeItem.item.mask |= TVIF_IMAGE;
if (iSelImage >= 0)
newTreeItem.item.mask |= TVIF_SELECTEDIMAGE;
HTREEITEM htiNew = tc.InsertItem(&newTreeItem);
if (htiNew)
tc.SetItemData(htiNew, (DWORD)nd);
return htiNew;
}
// Load Table
void CDbTreeView::LoadTable(CTreeCtrl &tc, HTREEITEM htiParent, TABLE *table)
{
if (htiParent)
ClearBranchNode(tc, tc.GetChildItem(htiParent), FALSE);
// 载入字段信息
for (int i = 0; i < table->field_count; i++)
{
FIELD *f = table->fields + i;
CString strTitle;
strTitle.Format(_T("%s"), f->name);
NODE_DATA *nd = new NODE_DATA;
if (nd)
{
nd->type = DATA_TYPE_FIELD;
nd->data = (BYTE *)f;
}
HTREEITEM hti = InsertTreeNode(tc, htiParent, TVI_LAST, strTitle, 0, 0, nd);
}
// 载入关键字
for (i = 0; i < table->key_count; i++)
{
KEY *k = table->keys + i;
CString strTitle = _T("");
for (int m = 0; m < k->field_count; m++)
{
FIELD *f = table->fields + k->fields[m];
strTitle += f->name;
if (m < k->field_count - 1)
strTitle += _T(" | ");
}
NODE_DATA *nd = new NODE_DATA;
if (nd)
{
nd->type = DATA_TYPE_KEY;
nd->data = (BYTE *)k;
}
HTREEITEM hti = InsertTreeNode(tc, htiParent, TVI_LAST, strTitle, 1, 1, nd);
}
}
void CDbTreeView::LoadDb()
{
ClearTree();
// 载入数据
HASH_DATA *data = dynamic_element(&m_hashEditDb.array, 0, HASH_DATA*);
int records = m_hashEditDb.records;
for (int i = 0; i < records; i++)
{
TABLE *table = (TABLE *)data[i].data;
// 加入表名称
CString strTitle = table->name;
NODE_DATA *nd = new NODE_DATA;