///////////////////////////////////////////////////// ///////////////////////////////////////////////////// // // GridLayout2D // ///////////////////////////////////////////////////// ///////////////////////////////////////////////////// #include "CKAll.h" #include "Layout.h" CKObjectDeclaration *FillBehaviorGridLayout2DDecl(); CKERROR CreateGridLayout2DProto(CKBehaviorPrototype** pproto); int GridLayout2D(const CKBehaviorContext& behcontext); //------------------------------------------------- // Creates a declaration of this behavior // //------------------------------------------------- CKObjectDeclaration *FillBehaviorGridLayout2DDecl() { CKObjectDeclaration *od = CreateCKObjectDeclaration("2D Grid Layout"); od->SetDescription("Organize as a grid a set of 2D entities into a 2D Frame"); // Category in Virtools interface od->SetCategory("Interface/Layouts"); /* rem: In: triggers the process.
Out: is activated when the process is completed.

Components Array: array containing only objects (Base Type only, not Parameter).
Margin: margins to add to the dimension of the target frame.
Horizontal Gap Size: horizontal space between the entities displaced.
Vertical Gap Size: vertical space between the entities displaced.
Resize: if checked, resizes the target frame to match the extents of the generated grid.
Set Parent: if checked, set the target as parent of the entities in the array.

The target determine the position of the grid. */ od->SetType( CKDLL_BEHAVIORPROTOTYPE); // Unique identifier of this prototype od->SetGuid(CKGUID(0x265f342c,0x95e466e6)); od->SetAuthorGuid(VIRTOOLS_GUID); od->SetAuthorName("Virtools"); od->SetVersion(0x00020000); // Function that will create the behavior prototype od->SetCreationFunction(CreateGridLayout2DProto); // Class ID of the objects to which the behavior can applied od->SetCompatibleClassId(CKCID_2DENTITY); return od; } //------------------------------------------------- // GridLayout2D behavior prototype creation function // //------------------------------------------------- CKERROR CreateGridLayout2DProto(CKBehaviorPrototype **pproto) { CKBehaviorPrototype *proto = CreateCKBehaviorPrototype("2D Grid Layout"); if(!proto) return CKERR_OUTOFMEMORY; // Input/Outputs declaration proto->DeclareInput("In"); proto->DeclareOutput("Out"); proto->DeclareInParameter("Components Array", CKPGUID_DATAARRAY); proto->DeclareInParameter("Margins", CKPGUID_RECT, "(10,10),(10,10)"); proto->DeclareInParameter("Horizontal Gap Size", CKPGUID_INT, "10"); proto->DeclareInParameter("Vertical Gap Size", CKPGUID_INT, "10"); proto->DeclareInParameter("Resize", CKPGUID_BOOL, "TRUE"); proto->DeclareInParameter("Set Parent", CKPGUID_BOOL, "FALSE"); proto->SetFlags(CK_BEHAVIORPROTOTYPE_NORMAL); proto->SetBehaviorFlags(CKBEHAVIOR_TARGETABLE); // Function that will be called upon behavior execution proto->SetFunction(GridLayout2D); *pproto = proto; return CK_OK; } //------------------------------------------------- // GridLayout2D behavior execution function // //------------------------------------------------- int GridLayout2D(const CKBehaviorContext& behcontext) { CKBehavior* beh = behcontext.Behavior; beh->ActivateInput(0, FALSE); // Get the reference 2D frame CK2dEntity* rootFrame = (CK2dEntity*)beh->GetTarget(); if( !(rootFrame && CKIsChildClassOf(rootFrame, CKCID_2DENTITY))) return CKBR_OWNERERROR; // Array to display CKDataArray* array = (CKDataArray*)beh->GetInputParameterObject(0); if(!array) return CKBR_PARAMETERERROR; int nbRow = array->GetRowCount(); int nbColumn = array->GetColumnCount(); if(nbRow == 0) { behcontext.Context->OutputToConsole("Invalid target array : No row"); return CKBR_PARAMETERERROR; } for(int c=0 ; c < nbColumn ; c++) { if(array->GetColumnType(c) != CKARRAYTYPE_OBJECT) { behcontext.Context->OutputToConsole("Invalid target array : column type"); return CKBR_PARAMETERERROR; } } // Get the layout parameters int horizontalGap = 10, verticalGap = 10; VxRect margins(10, 10, 10, 10); CKBOOL resize = TRUE, setParent = FALSE; beh->GetInputParameterValue(1, &margins); beh->GetInputParameterValue(2, &horizontalGap); beh->GetInputParameterValue(3, &verticalGap); beh->GetInputParameterValue(4, &resize); beh->GetInputParameterValue(5, &setParent); // Position of each entity in the group relative to the reference frame Vx2DVector currentPosition, currentSize; rootFrame->GetPosition(currentPosition); // Top-Left corner => must center the coordinates rootFrame->GetSize(currentSize); currentPosition.x += margins.left; currentPosition.y += margins.top; Vx2DVector pos(currentPosition), cellSize; int* maxH = NULL; int* maxV = NULL; if(resize) { float hMarginSize = margins.left + margins.right + (nbColumn - 1)*horizontalGap; float vMarginSize = margins.top + margins.bottom + (nbRow - 1)*verticalGap; cellSize.x = (currentSize.x - hMarginSize)/nbColumn; cellSize.y = (currentSize.y - vMarginSize)/nbRow; } else { maxV = new int[nbRow]; maxH = new int[nbColumn]; for(int j = 0 ; j < nbColumn ; j++) maxH[j] = 0; for(int i = 0 ; i < nbRow ; i++) { maxV[i] = 0; for(int j = 0 ; j < nbColumn ; j++) { CKObject* obj = (CKObject*) array->GetElementObject(i, j); if(CKIsChildClassOf(obj, CKCID_2DENTITY)) { ((CK2dEntity*)obj)->GetSize(cellSize); if(cellSize.x > maxH[j]) maxH[j] = (int)cellSize.x; if(cellSize.y > maxV[i]) maxV[i] = (int)cellSize.y; } } } } for(int i = 0 ; i < nbRow ; i++) { for(int j = 0 ; j < nbColumn ; j++) { CKObject* obj = (CKObject*)array->GetElementObject(i, j); if(CKIsChildClassOf(obj, CKCID_2DENTITY)) { CK2dEntity* ent = (CK2dEntity*)obj; if(resize) ent->SetSize(cellSize); ent->SetPosition(currentPosition); if(setParent) ent->SetParent(rootFrame); } currentPosition.x += (((resize)?(cellSize.x):(maxH[j])) + horizontalGap); } currentPosition.x = pos.x; currentPosition.y += (((resize)?(cellSize.y):(maxV[i])) + verticalGap); } if(!resize) { delete [] maxH; delete [] maxV; } // 'Out' beh->ActivateOutput(0); return CKBR_OK; }