|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
//文件 ActionDeleteItem.cpp
|
|
|
//主要功能:
|
|
|
//
|
|
|
//程序编写: 2006-12-07
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
#include "StdAfx.h"
|
|
|
#include ".\actiondeleteitem.h"
|
|
|
#include "SigmaDoc.h"
|
|
|
#include "SigmaView.h"
|
|
|
#include "Visitor.h"
|
|
|
#include "Util.h"
|
|
|
|
|
|
CActionDeleteItem::CActionDeleteItem(CSigmaDoc * ppDoc, UINT actionType)
|
|
|
: CActionItem(ppDoc, actionType)
|
|
|
, m_bDeleted(false)
|
|
|
, m_bPerformOperation(FALSE)
|
|
|
{
|
|
|
}
|
|
|
|
|
|
NAction::CActionDeleteItem::CActionDeleteItem()
|
|
|
: CActionItem(nullptr, 0)
|
|
|
{
|
|
|
}
|
|
|
|
|
|
CActionDeleteItem::CActionDeleteItem(CSigmaDoc * ppDoc, UINT actionType, const CPositionList& list)
|
|
|
: CActionItem(ppDoc, actionType)
|
|
|
, m_bDeleted(false)
|
|
|
, m_bPerformOperation(FALSE)
|
|
|
{
|
|
|
long num=(long)list.GetCount();
|
|
|
|
|
|
if(num>0)
|
|
|
{
|
|
|
POSITION pt;
|
|
|
POSITION pos = list.GetHeadPosition();
|
|
|
std::vector<POSITION> positions;
|
|
|
positions.reserve(list.GetSize());
|
|
|
|
|
|
while (pos != NULL)
|
|
|
{
|
|
|
pt = list.GetNext(pos);
|
|
|
COne *pOne=GetDoc()->GetDraw()->GetAt(pt);
|
|
|
value.AddTail(pOne);
|
|
|
positions.push_back(pt);
|
|
|
}
|
|
|
|
|
|
GetDoc()->GetDraw()->GetElementIndexs(positions, m_pos);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
CActionDeleteItem::~CActionDeleteItem(void)
|
|
|
{
|
|
|
Clear();
|
|
|
}
|
|
|
|
|
|
void NAction::CActionDeleteItem::Clear(void)
|
|
|
{
|
|
|
//Delete all objects in the m_list
|
|
|
if(m_bDeleted)//清除所有数据
|
|
|
{
|
|
|
CActionItem::Clear(value);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void NAction::CActionDeleteItem::accept(CActionVisitor& visitor)
|
|
|
{
|
|
|
visitor.visit(*this);
|
|
|
}
|
|
|
|
|
|
void CActionDeleteItem::Finish(void)
|
|
|
{
|
|
|
if(!m_bPerformOperation)
|
|
|
RemoveOperation();
|
|
|
CActionItem::Finish();
|
|
|
}
|
|
|
|
|
|
void CActionDeleteItem::RemoveOperation()
|
|
|
{
|
|
|
GetDoc()->ClearSelection();
|
|
|
m_bDeleted=true;
|
|
|
if(value.IsEmpty()) return;
|
|
|
|
|
|
// 注意:pOne->GetRange 会查找符号,而 AfxGetGlobalMark()->BackupMark() 获取的是一个 threadlocal 对象,
|
|
|
// 这时候里面当前符号表指针很可能已经指向别的图件的符号表了,所以需要重新设置,用完之后再还原
|
|
|
auto* pMark = &(GetDoc()->GetDraw()->mark);
|
|
|
AfxGetGlobalMark()->BackupMark();
|
|
|
AfxGetGlobalMark()->SetMark(pMark);
|
|
|
FinalAction finalAction([]() { AfxGetGlobalMark()->RestoreMark(); });
|
|
|
|
|
|
COne* pOne;
|
|
|
int n=0;
|
|
|
CRect8 range(1e100,-1e100,-1e100,1e100);
|
|
|
|
|
|
std::vector<COne*> pOnes;
|
|
|
pOnes.reserve(value.GetCount());
|
|
|
|
|
|
POSITION pos = value.GetTailPosition();
|
|
|
while (pos != NULL)
|
|
|
{
|
|
|
pOne = (COne*)value.GetPrev(pos);
|
|
|
pOne->GetRange(range);
|
|
|
pOnes.push_back(pOne);
|
|
|
}
|
|
|
|
|
|
RemoveAtNoClear(pOnes);
|
|
|
|
|
|
Invalidate(range);
|
|
|
//GetDoc()->Modified();
|
|
|
}
|
|
|
|
|
|
void CActionDeleteItem::AddOperation()
|
|
|
{
|
|
|
//add back all the objects according its position in the CDrawDoc::m_objects.
|
|
|
m_bDeleted=false;
|
|
|
if (value.IsEmpty())
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
size_t posSize = m_pos.size();
|
|
|
size_t valueSize = value.GetCount();
|
|
|
|
|
|
ASSERT(posSize == valueSize);
|
|
|
|
|
|
// 缓存下标和被删除的 COne* 映射关系,必须由小到大排列
|
|
|
std::vector<std::pair<int, COne*>> cache;
|
|
|
cache.reserve(posSize);
|
|
|
|
|
|
{
|
|
|
int index = 0;
|
|
|
POSITION pos = value.GetHeadPosition();
|
|
|
while (pos != nullptr)
|
|
|
{
|
|
|
COne* pOne = reinterpret_cast<COne*>(value.GetNext(pos));
|
|
|
cache.emplace_back(m_pos[index++], pOne);
|
|
|
}
|
|
|
|
|
|
std::sort(cache.begin(), cache.end(), [](auto& pair1, auto& pair2)
|
|
|
{
|
|
|
return pair1.first < pair2.first;
|
|
|
});
|
|
|
}
|
|
|
|
|
|
{
|
|
|
// 性能优化,65万个散点的文件,能够由一分钟缩短成几秒钟
|
|
|
// 注意这里,我们先遍历图件中的图元,然后标记当前下标,再判断 cache 中的下标和当前下标是否相同,如果相同,当前就是要插入的位置
|
|
|
// 我们前面对 cache 元素按下标排列的意义就来了,我们每次只用和 cache 的一个迭代器进行比较,如果这个元素插入到了原图件中,
|
|
|
// 就把迭代器向后移动一下就行,避免了大量循环
|
|
|
CPtrList* pValues = GetDoc()->GetDraw()->GetValueList();
|
|
|
int index = 0;
|
|
|
auto cacheIt = cache.begin();
|
|
|
POSITION pos = pValues->GetHeadPosition();
|
|
|
while (pos != nullptr)
|
|
|
{
|
|
|
// 如果缓存中的数据处理完了,整个操作就结束了
|
|
|
if (cacheIt == cache.end())
|
|
|
{
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
// 如果找到正确的位置
|
|
|
if (index == cacheIt->first)
|
|
|
{
|
|
|
pos = GetDoc()->GetDraw()->InsertElementBefore(pos, cacheIt->second); // 这里注意要把 pos 接上
|
|
|
cacheIt++;
|
|
|
}
|
|
|
|
|
|
pValues->GetNext(pos);
|
|
|
index++;
|
|
|
}
|
|
|
|
|
|
// 如果删除的图元在图件的末尾,还得把这部分添加回去
|
|
|
while (cacheIt != cache.end())
|
|
|
{
|
|
|
GetDoc()->GetDraw()->AddTailOne(cacheIt->second);
|
|
|
cacheIt++;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void CActionDeleteItem::Undo()
|
|
|
{
|
|
|
CActionItem::Undo();
|
|
|
AddOperation();
|
|
|
}
|
|
|
|
|
|
void CActionDeleteItem::Redo()
|
|
|
{
|
|
|
CActionItem::Redo();
|
|
|
RemoveOperation();
|
|
|
}
|