OpAlign Class Reference

Undo-able Op to Align objects. More...

#include <aligndlg.h>

Inheritance diagram for OpAlign:

TransOperation UndoableOperation Operation MessageHandler ListItem CCObject SimpleCCObject List of all members.

Public Member Functions

 OpAlign ()
 OpAlign constructor.
void DoWithParam (OpDescriptor *pOp, OpParam *pAlignParam)
 performs the desired align operation

Static Public Member Functions

static BOOL Init ()
 Creates an OpDescriptor for an Align operation.
static OpState GetState (String_256 *, OpDescriptor *)
 Returns the OpState of the OpAlign dialogue operation.

Private Member Functions

void AlignOneAxis (AlignType Align, INT32 NumObjs, XLONG SumObjWidths, INT32 SelRectLow, INT32 SelRectHigh, ObjInfo *x, INT32 *dx)
 aligns the object in one axis at a time, in the specified way (written as though for x, but same algorithm applies to y) distributing a single object leaves it unchanged.

Detailed Description

Undo-able Op to Align objects.

Author:
Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com>
Date:
30/09/94

Definition at line 207 of file aligndlg.h.


Constructor & Destructor Documentation

OpAlign::OpAlign  ) 
 

OpAlign constructor.

Author:
Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com>
Date:
29/9/94

Definition at line 749 of file aligndlg.cpp.

00749                  : TransOperation() 
00750 {
00751 }       


Member Function Documentation

void OpAlign::AlignOneAxis AlignType  Align,
INT32  NumObjs,
XLONG  SumObjWidths,
INT32  RectLow,
INT32  RectHigh,
ObjInfo x,
INT32 *  dx
[private]
 

aligns the object in one axis at a time, in the specified way (written as though for x, but same algorithm applies to y) distributing a single object leaves it unchanged.

/ extern "C" INT32 CompareObjInfoHigh(const void* elem1, const void* elem2) { ObjInfo* a=(ObjInfo*)elem1; ObjInfo* b=(ObjInfo*)elem2; if (a->hi == b->hi) return (a->i < b->i ? -1 : 1); // sort by Z order else return (a->hi < b->hi ? -1 : 1); } /*!/ extern "C" INT32 CompareObjInfoCentre(const void* elem1, const void* elem2) { ObjInfo* a=(ObjInfo*)elem1; ObjInfo* b=(ObjInfo*)elem2; INT32 d=(a->lo+a->hi)-(b->lo+b->hi); if (d==0) return (a->i < b->i ? -1 : 1); // sort by Z order else return ( d < 0 ? -1 : 1); }

/*!

Author:
Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com>
Date:
29/9/94

Definition at line 975 of file aligndlg.cpp.

00977 {
00978     INT32 i;
00979 
00980     switch (Align)
00981     {
00982         case DistributeLow:
00983             if (NumObjs==1)
00984                 dx[0]=0;
00985             else
00986             {
00987                 qsort(x,NumObjs,sizeof(ObjInfo),CompareObjInfoLow);
00988                 INT32 RectWidth=RectHigh-RectLow;
00989                 INT32 LastObjWidth =x[NumObjs-1].hi-x[NumObjs-1].lo;
00990                 INT32 gap=(RectWidth-LastObjWidth)/(NumObjs-1);
00991                 INT32 pos=RectLow;
00992                 for (i=0; i<NumObjs; i++)
00993                 {                                                                                                 
00994                     dx[x[i].i]=pos-x[i].lo;
00995                     pos+=gap;
00996                 }
00997             }
00998             break;
00999 
01000         case DistributeHigh:
01001             if (NumObjs==1)
01002                 dx[0]=0;
01003             else
01004             {
01005                 qsort(x,NumObjs,sizeof(ObjInfo),CompareObjInfoHigh);
01006                 INT32 RectWidth=RectHigh-RectLow;
01007                 INT32 FirstObjWidth=x[0].hi-x[0].lo;
01008                 INT32 gap=(RectWidth-FirstObjWidth)/(NumObjs-1);
01009                 INT32 pos=RectLow+FirstObjWidth;
01010                 for (i=0; i<NumObjs; i++)
01011                 {
01012                     dx[x[i].i]=pos-x[i].hi;
01013                     pos+=gap;
01014                 }
01015             }
01016             break;
01017 
01018         case DistributeCentre:
01019             if (NumObjs==1)
01020                 dx[0]=0;
01021             else
01022             {
01023                 qsort(x,NumObjs,sizeof(ObjInfo),CompareObjInfoCentre);
01024                 INT32 RectWidth=RectHigh-RectLow;
01025                 INT32 LastObjWidth =x[NumObjs-1].hi-x[NumObjs-1].lo;
01026                 INT32 FirstObjWidth=x[0].hi-x[0].lo;
01027                 INT32 gap=(RectWidth-(FirstObjWidth+LastObjWidth)/2)/(NumObjs-1);
01028                 INT32 pos=RectLow+FirstObjWidth/2;
01029                 for (i=0; i<NumObjs; i++)
01030                 {
01031                     dx[x[i].i]=pos-(x[i].hi+x[i].lo)/2;
01032                     pos+=gap;
01033                 }
01034             }
01035             break;
01036 
01037         case DistributeEqui:
01038             if (NumObjs==1)
01039                 dx[0]=0;
01040             else
01041             {
01042                 qsort(x,NumObjs,sizeof(ObjInfo),CompareObjInfoCentre);
01043                 INT32 RectWidth=RectHigh-RectLow;
01044                 INT32 gap=((XLONG)RectWidth-SumObjWidths)/(NumObjs-1);
01045                 INT32 pos=RectLow;
01046                 for (i=0; i<NumObjs; i++)
01047                 {
01048                     dx[x[i].i]=pos-x[i].lo;
01049                     pos+=gap+x[i].hi-x[i].lo;
01050                 }
01051             }
01052             break;
01053          
01054         case AlignLow:
01055             for (i=0; i<NumObjs; i++)
01056                 dx[i]=RectLow-x[i].lo;
01057             break;
01058 
01059         case AlignCentre:
01060             for (i=0; i<NumObjs; i++)
01061                 dx[i]=(RectHigh-x[i].hi+RectLow-x[i].lo)/2;
01062             break;
01063 
01064         case AlignHigh:
01065             for (i=0; i<NumObjs; i++)
01066                 dx[i]=RectHigh-x[i].hi;
01067             break;
01068 
01069         case AlignNone:
01070             for (i=0; i<NumObjs; i++)
01071                 dx[i]=0;
01072             break;
01073     }
01074 }

void OpAlign::DoWithParam OpDescriptor pOp,
OpParam pAlignParam
[virtual]
 

performs the desired align operation

Author:
Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com>
Date:
29/9/94

Reimplemented from TransOperation.

Definition at line 799 of file aligndlg.cpp.

00800 {
00801     // DMc alterations so that this works with compound nodes   
00802     SelRange   Selection(*(GetApplication()->FindSelection()));
00803 
00804     RangeControl rg = Selection.GetRangeControlFlags();
00805     rg.PromoteToParent = TRUE;
00806     Selection.Range::SetRangeControl(rg);
00807 
00808     DocRect     SelRect   = Selection.GetBoundingRect();
00809     DocRect     TargetRect;
00810     TargetRect.MakeEmpty();
00811     INT32        NumObjs   = Selection.Count();
00812     AlignParam* pAlign    =(AlignParam*)pAlignParam;
00813 
00814     BOOL moved=FALSE;                   // set to TRUE if any object is moved
00815     BeginSlowJob(-1,FALSE);
00816     BOOL OK=DoStartTransOp(FALSE);
00817 
00818     // find parent spread of first object in selection
00819     Node*   pFirstNode=NULL;
00820     Spread* pSpread   =NULL;
00821     if (OK)
00822     {
00823         pFirstNode=Selection.FindFirst();
00824         if (pFirstNode!=NULL)
00825             pSpread=pFirstNode->FindParentSpread();
00826         OK=(pSpread!=NULL);
00827         if (!OK)
00828             ERROR2RAW("OpAlign::DoWithParam() - could not find parent spread");
00829     }
00830 
00831     // Find the size of the target rectangle
00832     if (pAlign->target==ToSelection)
00833         TargetRect=SelRect;
00834     else
00835     {
00836         Page* pPage=pSpread->FindFirstPageInSpread();
00837         while (pPage)
00838         {
00839             DocRect PageRect=pPage->GetPageRect();
00840             if (pAlign->target==ToSpread || SelRect.IsIntersectedWith(PageRect))
00841                 TargetRect=TargetRect.Union(PageRect);
00842             pPage=pPage->FindNextPage();
00843         }
00844     }
00845 
00846     // allocate all dynamic memory required
00847     Node**   pObj=NULL;
00848     ObjInfo* x   =NULL;
00849     ObjInfo* y   =NULL;
00850     INT32*    dx  =NULL;
00851     INT32*    dy  =NULL;
00852     if (OK)         ALLOC_WITH_FAIL(pObj,(Node**)  CCMalloc(NumObjs*sizeof(Node*)),  this);
00853     if (pObj!=NULL) ALLOC_WITH_FAIL(x,   (ObjInfo*)CCMalloc(NumObjs*sizeof(ObjInfo)),this);
00854     if (   x!=NULL) ALLOC_WITH_FAIL(y,   (ObjInfo*)CCMalloc(NumObjs*sizeof(ObjInfo)),this);
00855     if (   y!=NULL) ALLOC_WITH_FAIL(dx,  (INT32*)   CCMalloc(NumObjs*sizeof(INT32)),   this);
00856     if (  dx!=NULL) ALLOC_WITH_FAIL(dy,  (INT32*)   CCMalloc(NumObjs*sizeof(INT32)),   this);
00857     OK=(dy!=NULL);
00858 
00859     // if memory claimed OK and target rect not empty proceed with op
00860     // (ie. do nothing if 'within page(s)' when no object on a page)
00861     DocRect EmptyRect;
00862     if (OK && TargetRect!=EmptyRect)
00863     {
00864         // create an array of pointers to objects (nodes) to be affected
00865         Node* pNode=Selection.FindFirst();
00866         INT32  i=0;
00867         while (pNode!=NULL)
00868         {
00869             if (pNode->IsBounded() && !((NodeRenderableBounded*)pNode)->GetBoundingRect(TRUE).IsEmpty())
00870                 pObj[i++]=pNode;
00871             pNode=Selection.FindNext(pNode);
00872         }
00873         NumObjs=i;
00874 
00875         // cache x & y info in separate arrays so they can be sorted separately
00876         XLONG SumObjWidths =0;
00877         XLONG SumObjHeights=0;
00878         for (i=0; i<NumObjs; i++)
00879         {
00880             DocRect ObjRect=((NodeRenderableBounded*)pObj[i])->GetBoundingRect();
00881             x[i].i=i;
00882             x[i].lo=ObjRect.lo.x;
00883             x[i].hi=ObjRect.hi.x;
00884             SumObjWidths+=ObjRect.hi.x-ObjRect.lo.x;
00885             y[i].i=i;
00886             y[i].lo=ObjRect.lo.y;
00887             y[i].hi=ObjRect.hi.y;
00888             SumObjHeights+=ObjRect.hi.y-ObjRect.lo.y;
00889         }
00890 
00891         // for each object, calculate the x and y displacements independently
00892         AlignOneAxis(pAlign->h,NumObjs,SumObjWidths, TargetRect.lo.x,TargetRect.hi.x,x,dx);
00893         AlignOneAxis(pAlign->v,NumObjs,SumObjHeights,TargetRect.lo.y,TargetRect.hi.y,y,dy);
00894 
00895         // apply the x and y displacements simultaneously to each object
00896         for (i=0; i<NumObjs; i++)
00897             if (dx[i]!=0 || dy[i]!=0)
00898             {
00899                 moved=TRUE;
00900                 Trans2DMatrix* pMatrix=new Trans2DMatrix(dx[i],dy[i]);
00901                 DoTransformNode((NodeRenderableInk*)pObj[i],pMatrix);
00902             }
00903     }
00904 
00905     // free up any memory which was allocated
00906     CCFree(dx);
00907     CCFree(dy);
00908     CCFree(x);
00909     CCFree(y);
00910     CCFree(pObj);
00911 
00912     if (moved)
00913     {
00914         Document::GetSelected()->ForceRedraw(pSpread, TargetRect);
00915         GetApplication()->UpdateSelection();
00916     }
00917     else
00918         FailAndExecute();
00919     End();
00920     EndSlowJob();
00921 }

OpState OpAlign::GetState String_256 pString,
OpDescriptor pOpDesc
[static]
 

Returns the OpState of the OpAlign dialogue operation.

Author:
Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com>
Date:
29/9/94

Reimplemented from TransOperation.

Definition at line 786 of file aligndlg.cpp.

00787 {
00788     return ArrangeAlignment::GetState(pString, pOpDesc);
00789 }

BOOL OpAlign::Init void   )  [static]
 

Creates an OpDescriptor for an Align operation.

Author:
Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com>
Date:
30/9/94
Returns:
FALSE if it fails (due to lack of memory)

Reimplemented from SimpleCCObject.

Definition at line 762 of file aligndlg.cpp.

00763 {  
00764     return RegisterOpDescriptor(
00765         0,                          // Tool ID
00766         _R(IDS_OPALIGN),                // String resource ID
00767         CC_RUNTIME_CLASS(OpAlign),  // Runtime class
00768         OPTOKEN_OPALIGN,            // Token string
00769         OpAlign::GetState,          // GetState function
00770         0,                          // Help ID
00771         0,                          // Bubble ID
00772         0,                          // Resource ID
00773         0                           // Control ID
00774 //  needs   'GREY_WHEN_NO_CURRENT_DOC'
00775     );
00776 }   


The documentation for this class was generated from the following files:
Generated on Sat Nov 10 03:57:25 2007 for Camelot by  doxygen 1.4.4