// ObjBoxList.cpp: implementation of the CObjBoxList class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "ObjBoxList.h"
#include "misc.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CObjBoxList::CObjBoxList()
{
this->index = NULL;
this->top = 0;
this->snag_to_grid = TRUE;
this->grid_size = 5;
this->is_modified = FALSE;
}
CObjBoxList::~CObjBoxList()
{
this->Destroy();
}
int CObjBoxList::Init(long init_size)
{
int i;
this->top = 0;
this->size = init_size;
MALLOC(this->index,CObjBox * ,this->size);
for(i = 0; i < this->size; i++)
this->index[i] = NULL;
return OK;
}
int CObjBoxList::Destroy()
{
int i;
if(this->index == NULL)
return ERROR;
for(i = 0; i < this->size; i++)
{
if(this->index[i])
{
this->index[i]->Destroy();
DEL(this->index[i]);
}
}
FREE(this->index);
this->index=NULL;
this->top=0;
this->size=0;
return OK;
}
int CObjBoxList::IsEmpty()
{
if(this->top <= 0)
return TRUE;
else
return FALSE;
}
int CObjBoxList::IsFull()
{
if(this->top >= this->size)
return TRUE;
return FALSE;
}
int CObjBoxList::Push(CObjBox *node)
{
CObjBox *p;
p = this->PushEmpty();
if(p == NULL)
return ERROR;
p->Copy(node);
return OK;
}
int CObjBoxList::Pop(CObjBox *node)
{
if(this->IsEmpty())
return ERROR;
this->top--;
node->Copy(this->index[this->top]);
this->index[this->top]->Destroy();
DEL(this->index[this->top]);
return OK;
}
int CObjBoxList::Print()
{
int i;
for(i = 0; i <this->top; i++)
{
this->index[i]->Print();
LOG(",");
}
LOG("\n");
LOG("size=%%ld\n",this->size);
LOG("top=%%ld\n",this->top);
LOG("bottom=%%ld\n",0);
return OK;
}
long CObjBoxList::GetLen()
{
return this->top;
}
long CObjBoxList::Search_Pos(CObjBox *node)
{
int i;
for(i=0;i<this->top;i++)
{
if(this->index[i]->Comp(node) == 0)
return i;
}
return -1;
}
CObjBox * CObjBoxList::Search(CObjBox *node)
{
long pos = this->Search_Pos(node);
if(pos >= 0 && pos < this->top)
return this->index[pos];;
return NULL;
}
CObjBox * CObjBoxList::GetTop()
{
if(this->IsEmpty())
return NULL;
return this->index[this->top - 1];
}
int CObjBoxList::DelTop()
{
if(this->IsEmpty())
return ERROR;
this->top--;
this->index[this->top]->Destroy();
DEL(this->index[this->top]);
return OK;
}
int CObjBoxList::Clear()
{
while(this->DelTop());
return OK;
}
CObjBox *CObjBoxList::PushEmpty()
{
if(this->IsFull())
{
REALLOC(this->index,CObjBox *,this->size * 2);
this->size *= 2;
for(int i = this->top; i < this->size; i++)
{
this->index[i] = 0;
}
}
NEW(this->index[this->top] , CObjBox );
this->index[this->top]->Init();
this->top++;
return this->index[this->top - 1];
}
CObjBox * CObjBoxList::GetElem(long index)
{
if(index < 0 || index >= this->top)
return NULL;
return this->index[index];
}
int CObjBoxList::Sort(int order)
{
long i,j,c;
CObjBox *pt;
for(j=this->GetLen(); j > 0; j--)
{
for(i = 0; i < j - 1; i++)
{
if(order==0)
c = index[i]->Comp(index[i+1]) > 0;
else
c = index[i]->Comp(index[i+1]) < 0;
if(c)
{
pt = index[i];
index[i] = index[i + 1];
index[i + 1] = pt;
}
}
}
return OK;
}
CObjBox * CObjBoxList::BSearch_CObjBox(CObjBox *node,int order)
{
long i;
i = this->BSearch(node,order);
return this->GetElem(i);
}
long CObjBoxList::BSearch(CObjBox *node,int order)
{
int find,pos;
pos = this->BSearch_Pos(node,order,&find);
if(find) return pos;
return -1;
}
int CObjBoxList::InsertElem(long i, CObjBox *node)
{
//insert a node at pos i
CObjBox *new_node;
ASSERT(i >= 0 && i <= this->top);
//Add a new node
new_node = this->PushEmpty();
ASSERT(new_node);
//copy value
new_node->Copy(node);
for(int k = this->top - 1; k >= i; k--)
{
this->index[k] = this->index[k - 1];
}
this->index[i] = new_node;
return OK;
}
int CObjBoxList::DelElem(long i)
{
CObjBox *p;
ASSERT(i >= 0 && i < this->top);
p = this->GetElem(i);
DEL(p);
for(int k = i; k < this->top; k++)
{
this->index[k] = this->index[k + 1];
}
this->top --;
this->index[top] = NULL;
return OK;
}
int CObjBoxList::InsOrdered(CObjBox *node, int order,int unique)
{
int pos,find;
pos = this->BSearch_Pos(node,order,&find);
if(find && unique)
return ERROR;
return this->InsertElem(pos,node);
}
long CObjBoxList::BSearch_Pos(CObjBox *node, int order, int *find_flag)
{
long low,high,mid,c;
long flag = 0,pos = -1;
ASSERT(order == 0 || order == 1);
low = 0; high=this->GetLen() - 1;
while(low<=high)
{
mid = (low+high)/2;
if(node->Comp(this->index[mid]) == 0)
{
*find_flag = TRUE;
return mid;
}
if(order == 0)
c = this->index[mid]->Comp(node) > 0;
else
c = this->index[mid]->Comp(node) < 0;
if(c)
high = mid-1;
else
low = mid+1;
}
*find_flag = FALSE;
return low;
}
//////////////////////////////////////////////////////////
//below is my own code
//////////////////////////////////////////////////////////
int CObjBoxList::SetCanvas(CCanvas *canvas)
{
CObjBox *pobj;
for(int i = 0; i< this->GetLen(); i++)
{
pobj = this->GetElem(i);
ASSERT(pobj);
pobj->SetCanvas(canvas);
}
return OK;
}
int CObjBoxList::PtInWhich(int x, int y)
{
CObjBox *pobj;
for(int i = this->GetLen() - 1; i >= 0; i--)
{
pobj = this->GetElem(i);
ASSERT(pobj);
if(pobj->PtInRect(x,y))
return i;
}
return -1;
}
int CObjBoxList::SetSel(int i,BOOL flag)
{
CObjBox *pobj;
pobj = this->GetElem(i);
if(pobj)
{
pobj->SetSel(flag);
this->SelInSameGroup(pobj);
return OK;
}
return ERROR;
}
int CObjBoxList::CancelAllSel()
{
CObjBox *pobj;
for(int i = 0; i< this->GetLen(); i++)
{
pobj = this->GetElem(i);
ASSERT(pobj);
pobj->SetSel(0);
}
return OK;
}
int CObjBoxList::GetSelNum()
{
int c = 0;
CObjBox *p;
for(int i = 0; i< this->GetLen(); i++)
{
p = this->GetElem(i);
ASSERT(p);
if(p->selected)
c++;
}
return c;
}
int CObjBoxList::GetFirstSel()
{
CObjBox *p;
for(int i = this->GetLen() - 1; i >= 0; i--)
{
p = this->GetElem(i);
ASSERT(p);
if(p->selected)
return i;
}
return -1;
}
int CObjBoxList::OffsetAllSel(int cx, int cy)
{
CObjBox *pobj;
for(int i = 0; i<this->GetLen(); i++)
{
pobj = this->GetElem(i);
ASSERT(pobj);
if(pobj->selected)
{
this->SetModifyFlag(TRUE);
pobj->Offset(cx,cy);
pobj->CalcuResizeBoxPos();
}
}
return OK;
}
int CObjBoxList::DelSel()
{
CObjBox *pobj;
for(int i = 0; i < this->GetLen(); i++)
{
pobj = this->GetElem(i);
ASSERT(pobj);
if(pobj->selected)
{
this->DelElem(i);
this->SetModifyFlag(TRUE);
i --; //DelElem will move the elements
}
}
return OK;
}
int CObjBoxList::SetSel(int l, int t, int r, int b)
{
CRect sel_rect;
CObjBox *pobj;
sel_rect.Init();
sel_rect.SetRect(l,t,r,b);
for(int i = 0; i < this->GetLen(); i++)
{
pobj = this->GetElem(i);
ASSERT(pobj);
if(pobj->IsIntersect(&sel_rect))
{
pobj->SetSel(TRUE);
this->SelInSameGroup(pobj);
}
}
return OK;
}
int CObjBoxList::SwapObj(int i, int j)
{
if(i == j)
return OK;
if( i < 0 || i >= this->GetLen())
return ERROR;
if( j < 0 || j >= this->GetLen())
return ERROR;
CObjBox *ptr = this->GetElem(i);
this->index[i] = this->GetElem(j);
this->index[j] = ptr;
this->SetModifyFlag(TRUE);
return OK;
}
int CObjBoxList::AlignSelLeft()
{
int i,min_left;
CObjBox *pobj;
min_left = this->GetSelMinLeft();
for(i = 0; i<this->GetLen(); i++)
{
pobj = this->GetElem(i);
ASSERT(pobj);
if(pobj->selected)
{
if(pobj->GetWidth() > 0)
pobj->SetLeft(min_left);
else
pobj->SetRight(min_left);
this->SetModifyFlag(TRUE);
pobj->CalcuResizeBoxPos();
}
}
return OK;
}
int CObjBoxList::AlignSelRight()
{
int i,max_right = MIN_INT;
CObjBox *pobj;
CRect rt;
for(i = 0; i<this->GetLen(); i++)
{
pobj = this->GetElem(i);
ASSERT(pobj);
if(pobj->selected)
{
rt.Copy(pobj);
rt.Normalize();
if(rt.right > max_right)
max_right = rt.right;
}
}
for(i = 0; i<this->GetLen(); i++)
{
pobj = this->GetElem(i);
ASSERT(pobj);
if(pobj->selected)
{
if(pobj->GetWidth() > 0)
pobj->SetRight(max_right);
else
pobj->SetLeft(max_right);
this->SetModifyFlag(TRUE);
pobj->CalcuResizeBoxPos();
}
}
return OK;
}
int CObjBoxList::AlignSelTop()
{
int i,min_top;
CObjBox *pobj;
min_top = this->GetSelMinTop();
for(i = 0; i<this->GetLen(); i++)
{
pobj = this->GetElem(i);
ASSERT(pobj);
if(pobj->selected)
{
if(pobj->GetHeight() > 0)
pobj->SetTop(min_top);
else
pobj->SetBottom(min_top);
this->SetModifyFlag(TRUE);
pobj->CalcuResizeBoxPos();
}
}
return OK;
}
int CObjBoxList::AlignSelBottom()
{
int i,max_bottom = MIN_INT;
CObjBox *pobj;
CRect rt;
for(i = 0; i<this->GetLen(); i++)
{
pobj = this->GetElem(i);
ASSERT(pobj);
if(pobj->selected)
{
rt.Copy(pobj);
rt.Normalize();
if(rt.bottom > max_bottom)
max_bottom = rt.bottom;
}
}
for(i = 0; i<this->GetLen(); i++)
{
pobj = this->GetElem(i);
ASSERT(pobj);
if(pobj->selected)
{
if(pobj->GetHeight() > 0)
pobj->SetBottom(max_bottom);
else
pobj->SetTop(max_bottom);
this->SetModifyFlag(TRUE);
pobj->CalcuResizeBoxPos();
}
}
return OK;
}
int CObjBoxList::GetUniqueGroupNum()
{
static int i = 1000;
return i++;
}
int CObjBoxList::GroupSel()
{
int i,g;
CObjBox *pobj;
g = this->GetUniqueGroupNum();
for(i = 0; i<this->GetLen(); i++)
{
pobj = this->GetElem(i);
ASSERT(pobj);
if(pobj->selected)
{
pobj->group_num = g;
this->SetModifyFlag(TRUE);
}
}
return OK;
}
int CObjBoxList::UngroupSel()
{
CObjBox *pobj;
for(int i = 0; i<this->GetLen(); i++)
{
pobj = this->GetElem(i);
ASSERT(pobj);
if(pobj->selected)
{
pobj->group_num = 0;
this->SetModifyFlag(TRUE);
}
}
return OK;
}
int CObjBoxList::SelInSameGroup(CObjBox *pobj)
{
ASSERT(pobj);
if(pobj->group_num == 0)
return ERROR;
CObjBox *p;
for(int i = 0; i<this->GetLen(); i++)
{
p = this->GetElem(i);
ASSERT(p);
if(pobj->group_num == p->group_num)
p->SetSel(TRUE);
}
return OK;
}
int CObjBoxList::PutSelToClipBoard()
{
CObjBox *pobj;
for(int i = 0; i < this->GetLen(); i++)
{
pobj = this->GetElem(i);
ASSERT(pobj);
pobj->is_copied =FALSE; // clear all copy flag
if(pobj->selected)
pobj->is_copied = TRUE;
}
return OK;
}
int CObjBoxList::IsClipBoardEmpty()
{
CObjBox *pobj;
for(int i = 0; i < this->GetLen(); i++)
{
pobj = this->GetElem(i);
ASSERT(pobj);
if(pobj->is_copied)
return FALSE;
}
return OK;
}
int CObjBoxList::GetSelMinLeft()
{
int i,min_left = MAX_INT;
CObjBox *pobj;
CRect rt;
for(i = 0; i<this->GetLen(); i++)
{
pobj = this->GetElem(i);
ASSERT(pobj);
if(pobj->selected)
{
rt.Copy(pobj);
rt.Normalize();
if(rt.left < min_left)
min_left = rt.left;
}
}
return min_left;
}
int CObjBoxList::GetSelMinTop()
{
int i,min_top = MAX_INT;
CObjBox *pobj;
CRect rt;
for(i = 0; i<this->GetLen(); i++)
{
pobj = this->GetElem(i);
ASSERT(pobj);
if(pobj->selected)
{
rt.Copy(pobj);
rt.Normalize();
if(rt.top < min_top)
min_top = rt.top;
}
}
return min_top;
}
int CObjBoxList::GetCopiedMinTop()
{
int i,min_top = MAX_INT;
CObjBox *pobj;
CRect rt;
for(i = 0; i<this->GetLen(); i++)
{
pobj = this->GetElem(i);
ASSERT(pobj);
if(pobj->is_copied)
{
rt.Copy(pobj);
rt.Normalize();
if(rt.top < min_top)
min_top = rt.top;
}
}
return min_top;
}
int CObjBoxList::GetCopiedMinLeft()
{
int i,min_left = MAX_INT;
CObjBox *pobj;
CRect rt;
for(i = 0; i<this->GetLen(); i++)
{
pobj = this->GetElem(i);
ASSERT(pobj);
if(pobj->is_copied)
{
rt.Copy(pobj);
rt.Normalize();
if(rt.left < min_left)
min_left = rt.left;
}
}
return min_left;
}
int CObjBoxList::Paste(int x, int y)
{
int old_len = this->GetLen();
int cx = x - this->GetCopiedMinLeft();
int cy = y - this->GetCopiedMinTop();
CObjBox *pobj,*pnew;
this->CancelAllSel();
for(int i = 0; i<old_len; i++)
{
pobj = this->GetElem(i);
ASSERT(pobj);
if(pobj->is_copied)
{
pnew = this->PushEmpty();
ASSERT(pnew);
pnew->Copy(pobj);
pnew->SetSel(TRUE);
pnew->Offset(cx,cy);
pnew->CalcuResizeBoxPos();
this->SetModifyFlag(TRUE);
}
}
return OK;
}
int CObjBoxList::GetSelMaxWidth()
{
CObjBox *pobj;
int max_width = MIN_INT;
for(int i = 0; i<this->GetLen(); i++)
{
pobj = this->GetElem(i);
ASSERT(pobj);
if(pobj->selected)
{
if(abs(pobj->GetWidth() > max_width))
max_width = abs(pobj->GetWidth());
}
}
return max_width;
}
int CObjBoxList::GetSelMaxHeight()
{
CObjBox *pobj;
int max_width = MIN_INT;
for(int i = 0; i<this->GetLen(); i++)
{
pobj = this->GetElem(i);
ASSERT(pobj);
if(pobj->selected)
{
if(abs(pobj->GetHeight() > max_width))
max_width = abs(pobj->GetHeight());
}
}
return max_width;
}
int CObjBoxList::SameSelWidth()
{
int max = this->GetSelMaxWidth();
CObjBox *pobj;
for(int i = 0; i<this->GetLen(); i++)
{
pobj = this->GetElem(i);
ASSERT(pobj);
if(pobj->selected)
{
if(pobj->GetWidth() > 0)
pobj->SetWidth(max);
else
pobj->SetWidth(-max);
this->SetModifyFlag(TRUE);
pobj->CalcuResizeBoxPos();
}
}
return OK;
}
int CObjBoxList::SameSelHeight()
{
int max = this->GetSelMaxHeight();
CObjBox *pobj;
for(int i = 0; i<this->GetLen(); i++)
{
pobj = this->GetElem(i);
ASSERT(pobj);
if(pobj->selected)
{
if(pobj->GetHeight() > 0)
pobj->SetHeight(max);
else
pobj->SetHeight(-max);
this->SetModifyFlag(TRUE);
pobj->CalcuResizeBoxPos();
}
}
return OK;
}
int CObjBoxList::SameSelSize()
{
this->SameSelHeight();
this->SameSelWidth();
return OK;
}
int CObjBoxList::Resize(int resize_obj,int resize_type,int x, int y,int is_square)
{
CObjBox *pobj;
int x1,y1,x2,y2;
if(this->snag_to_grid)
{
x = x - x % this->grid_size;
y = y - y % this->grid_size;
}
pobj = this->GetElem(resize_obj);
ASSERT(pobj);
pobj->GetResizePt(resize_type,&x1,&y1);
for(int i = 0; i < this->GetLen(); i++)
{
pobj = this->GetElem(i);
ASSERT(pobj);
if(pobj->selected)
{
this->SetModifyFlag(TRUE);
pobj->GetResizePt(resize_type,&x2,&y2);
pobj->Expand(resize_type,x+(x2 - x1),y + (y2 - y1),is_square);
pobj->CalcuResizeBoxPos();
}
}
return OK;
}
int CObjBoxList::PtInResizeBox(int x,int y,int *type)
{
ASSERT(type);
CObjBox *pobj;
int t;
*type = CResizeBox::TYPE_ERR;
for(int i = 0; i < this->GetLen(); i++)
{
pobj = this->GetElem(i);
ASSERT(pobj);
if(pobj->selected)
{
t = pobj->PtInResizeBox(x,y);
if(t != CResizeBox::TYPE_ERR)
{
*type = t;
break;
}
}
}
return i;
}
int CObjBoxList::CalAllDragOffset(int x, int y)
{
CObjBox *pobj;
for(int i = 0; i < this->GetLen(); i++)
{
pobj = this->GetElem(i);
ASSERT(pobj);
if(pobj->selected)
{
pobj->CalDragOffset(x,y);
}
}
return OK;
}
int CObjBoxList::MoveSelToMouse(int x, int y)
{
CObjBox *pobj;
for(int i = 0; i < this->GetLen(); i++)
{
pobj = this->GetElem(i);
ASSERT(pobj);
if(pobj->selected)
{
pobj->SetPos(x-pobj->drag_offx,y-pobj->drag_offy);
this->SetModifyFlag(TRUE);
if(this->snag_to_grid)
pobj->SnagToDrid(this->grid_size);
pobj->CalcuResizeBoxPos();
}
}
return OK;
}
int CObjBoxList::SaveToFile(CFileBase *file)
{
ASSERT(file);
int i;
CObjBox *pobj;
CMem mem;
LOCAL_MEM(mem);
file->SetSize(0);
file->Puts("<?xml version=\"1.0\" encoding=\"gb2312\"?>\r\n");
file->Puts("<AllObjects>\r\n");
for(i = 0; i<this->GetLen(); i++)
{
pobj = this->GetElem(i);
ASSERT(pobj);
pobj->i_xml_node->GetPath(&mem);
file->Printf("<objbox xml_path=\"%s\" group=\"%d\">\r\n",mem.p,pobj->group_num);
file->Printf("<rect left=\"%d\" top=\"%d\" right=\"%d\" bottom=\"%d\"/>\r\n",
pobj->left,pobj->top,pobj->right,pobj->bottom);
file->Printf("<code>\r\n");
file->Printf("<![CDATA[\r\n");
file->WriteFile(pobj->mf_user_attrib);
file->Printf("\r\n]]>\r\n");
file->Printf("</code>\r\n");
file->Printf("</objbox>\r\n");
}
file->Puts("</AllObjects>\r\n");
this->SetModifyFlag(FALSE);
return OK;
}
int CObjBoxList::SaveToFile(char *fn)
{
CFile file;
file.Init();
ASSERT(file.OpenFile(fn,"wb+"));
this->SaveToFile(&file);
file.CloseFile();
return OK;
}
int CObjBoxList::SetModifyFlag(BOOL flag)
{
this->is_modified = flag;
return OK;
}
int CObjBoxList::ToBack(int i)
{
ASSERT(i >= 0 && i < this->GetLen());
CObjBox *p = this->GetElem(i);
for(int k = i ; k > 0; k--)
{
this->index[k] = this->index[k - 1];
this->SetModifyFlag(TRUE);
}
this->index[0] = p;
return OK;
}
int CObjBoxList::ToFront(int i)
{
ASSERT(i >= 0 && i < this->GetLen());
CObjBox *p = this->GetElem(i);
for(int k = i; k < top - 1; k++)
{
this->index[k] = this->index[k + 1];
this->SetModifyFlag(TRUE);
}
if(top > 0)
this->index[top - 1] = p;
return OK;
}
int CObjBoxList::SelectAll()
{
CObjBox *pobj;
for(int i = 0; i < this->GetLen(); i++)
{
pobj = this->GetElem(i);
ASSERT(pobj);
pobj->SetSel(TRUE);
}
return OK;
}
int CObjBoxList::NormalizeSel()
{
CObjBox *pobj;
for(int i = 0; i < this->GetLen(); i++)
{
pobj = this->GetElem(i);
ASSERT(pobj);
if(pobj->selected)
{
pobj->Normalize();
}
}
return OK;
}