#include <aligndlg.h>
Inheritance diagram for OpAlign:
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. |
Definition at line 207 of file aligndlg.h.
|
OpAlign constructor.
Definition at line 749 of file aligndlg.cpp. 00749 : TransOperation() 00750 { 00751 }
|
|
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); } /*!
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 }
|
|
performs the desired align operation
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 }
|
|
Returns the OpState of the OpAlign dialogue operation.
Reimplemented from TransOperation. Definition at line 786 of file aligndlg.cpp. 00787 { 00788 return ArrangeAlignment::GetState(pString, pOpDesc); 00789 }
|
|
Creates an OpDescriptor for an Align operation.
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 }
|