// RoughLateralSpine.c #include "RoughLateralSpine.h" #include #include "utils.h" // CP# means Control Point or Handle // // // CP0 *************************** // * // * // * // * // * // CP1 *************************** //************************************************************************************** // // Functions for RoughLateralSpine // //************************************************************************************* L_VOID RoughLateralSpine_AddHandle(HANNOBJECT hObject, ANNPOINT apt, pHANDLEDEF pHandleDef) { L_UINT uFlags = ANNHANDLE_LOCATION | ANNHANDLE_CONTAINER_COORDINATES | ANNHANDLE_ID | ANNHANDLE_PEN_COLOR | ANNHANDLE_FILL_COLOR | ANNHANDLE_SHAPE; ANNHANDLE AnnHandle; AnnHandle.uStructSize = sizeof(ANNHANDLE); AnnHandle.nShape = pHandleDef->nShape; AnnHandle.crPen = RGB(0,0,0); AnnHandle.hCursor= NULL; AnnHandle.aptContainer = apt; AnnHandle.nID = pHandleDef->nID; AnnHandle.crFill = pHandleDef->crFill; AnnHandle.uFlags = uFlags; L_AnnAddUserHandle(hObject, &AnnHandle); } #define ROUGHLATERALSPINE_NUMPOINTS 2 HANDLEDEF RoughLateralSpine_HandleDef[ROUGHLATERALSPINE_NUMPOINTS] = { HANDLE_ID_CP0, ANNHANDLE_SHAPE_CIRCLE, RGB(0,0,0), HANDLE_ID_CP1, ANNHANDLE_SHAPE_CIRCLE, RGB(255,0,0), }; L_VOID RoughLateralSpine_AddUserHandles(HANNOBJECT hLineSide) { ANNPOINT aptLine[2]; L_AnnGetPoints(hLineSide, aptLine); // swap so that aptLine[0] is above aptLine[1] if (aptLine[0].y > aptLine[1].y) SwapAnnPoints(aptLine + 0, aptLine + 1); RoughLateralSpine_AddHandle(hLineSide, aptLine[0], RoughLateralSpine_HandleDef + 0); RoughLateralSpine_AddHandle(hLineSide, aptLine[1], RoughLateralSpine_HandleDef + 1); } //*************** RoughLateralSpine Create functions #define NUM_WIDTHS (2) // Sets the width of hLine (top and bottom horizontal lines) // The line width is two times the width of the hContainer // If the width of the top or bottom line becomes less than two container widths, // then resize the line L_VOID RoughLateralSpine_AnnSetLineWidth(HANNOBJECT hLine, HANNOBJECT hContainer) { ANNRECT arcContainer; ANNPOINT aptLine[2]; ANNPOINT aptNew[2]; L_DOUBLE dWidth; L_DOUBLE dDistRight; L_AnnGetRect(hContainer, &arcContainer, NULL); dWidth = arcContainer.right - arcContainer.left; L_AnnGetPoints(hLine, aptLine); // Swap points to that aptLine[0] is to the left of aptLine[1] if (aptLine[0].x > aptLine[1].x) { ANNPOINT aptTemp; aptTemp = aptLine[0]; aptLine[0] = aptLine[1]; aptLine[1] = aptTemp; } dDistRight = ABS(aptLine[1].x - aptLine[0].x); if (dDistRight < NUM_WIDTHS * dWidth) { aptNew[0] = aptLine[0]; aptNew[1].x = arcContainer.right + NUM_WIDTHS * dWidth; aptNew[1].y = aptNew[0].y; L_AnnSetPoints(hLine, aptNew, 2); } } HANNOBJECT RoughLateralSpine_CreateLine(HANNOBJECT hContainer, POINT pt0, L_UINT uTool, L_INT nID) { HANNOBJECT hLine; L_AnnCreateItem(hContainer, ANNOBJECT_LINE, FALSE, &hLine); L_AnnDefine(hLine, &pt0, ANNDEFINE_BEGINSET); L_AnnDefine(hLine, &pt0, ANNDEFINE_END); RoughLateralSpine_AnnSetLineWidth(hLine, hContainer); AnnSetID(hLine, uTool, nID); //Set tag to identify line 0,1,2 L_AnnSetVisible(hLine, TRUE, 0, NULL); L_AnnSetSelected(hLine, TRUE, 0); HideDefaultHandles(hLine); return hLine; } L_VOID RoughLateralSpine_LButtonDown(HWND hWnd, LPCHILDDATA pData) { L_AnnAddUndoNode(pData->hAutomation); L_AnnCreateItem(pData->hContainer, ANNOBJECT_LINE, FALSE, &pData->ObjectRoughLateralSpine.hLineSide); L_AnnDefine(pData->ObjectRoughLateralSpine.hLineSide, &pData->ptStart, ANNDEFINE_BEGINSET); pData->fCapture = TRUE; L_AnnRestrictCursor(pData->hContainer, NULL, NULL, &pData->rcOldClip, TRUE); } L_VOID RoughLateralSpine_MouseMove(LPCHILDDATA pData) { L_AnnDefine(pData->ObjectRoughLateralSpine.hLineSide, &pData->ptMove, ANNDEFINE_UPDATE); } L_VOID RoughLateralSpine_LButtonUp(LPCHILDDATA pData, L_UINT uTool) { POINT ptStart, ptEnd; if (pData->ptStart.y > pData->ptEnd.y) { ptStart = pData->ptEnd; ptEnd = pData->ptStart; } else { ptStart = pData->ptStart; ptEnd = pData->ptEnd; } L_AnnDefine(pData->ObjectRoughLateralSpine.hLineSide, &pData->ptEnd, ANNDEFINE_END); AnnSetID(pData->ObjectRoughLateralSpine.hLineSide, uTool, 0); //Set tag to identify line 0,1,2 L_AnnSetVisible(pData->ObjectRoughLateralSpine.hLineSide, TRUE, 0, NULL); L_AnnSetSelected(pData->ObjectRoughLateralSpine.hLineSide, TRUE, 0); HideDefaultHandles(pData->ObjectRoughLateralSpine.hLineSide); // Create top line RoughLateralSpine_CreateLine(pData->hContainer, ptStart, uTool, 1); // Create bottom line RoughLateralSpine_CreateLine(pData->hContainer, ptEnd, uTool, 2); //Bring the first line to the front of the z-order //This line will have all the user handles L_AnnBringToFront(pData->ObjectRoughLateralSpine.hLineSide); // Add user handles RoughLateralSpine_AddUserHandles(pData->ObjectRoughLateralSpine.hLineSide); // set the default settings from the automation object, and group the objects L_AnnSetAutoDefaults(pData->hAutomation, pData->hContainer, ANNFLAG_SELECTED|ANNFLAG_RECURSE); L_AnnGroup(pData->hContainer, ANNFLAG_SELECTED|ANNFLAG_RECURSE, NULL); } //*************** RoughLateralSpine Update functions #define ROUGH_LATERAL_SPINE_MIN_DIST (4) L_VOID RoughLateralSpine_RestrictPoint(LPCHILDDATA pData, HANNOBJECT hLine) { POINT ptMin, ptMax; RECT rcClip; ANNRECT arcContainer; GetClipCursor(&pData->rcOldClip); rcClip = pData->rcOldClip; L_AnnGetRect(pData->hContainer, &arcContainer, NULL); L_AnnConvert(pData->hContainer, (LPPOINT)&rcClip, (pANNPOINT)&arcContainer, 2, ANNCONVERT_TO_CLIENT); switch(pData->nUserHandleID) { case HANDLE_ID_CP0: GetHandleInfo(hLine, HANDLE_ID_CP1, &ptMax, NULL, NULL); rcClip.bottom = ptMax.y - ROUGH_LATERAL_SPINE_MIN_DIST + 1; break; case HANDLE_ID_CP1: GetHandleInfo(hLine, HANDLE_ID_CP0, &ptMin, NULL, NULL); rcClip.top = ptMin.y + ROUGH_LATERAL_SPINE_MIN_DIST; break; } L_AnnRestrictCursor(pData->hContainer, &rcClip, NULL, NULL, FALSE); } L_VOID RoughLateralSpine_Handle_LButtonDown(LPCHILDDATA pData, pANNMOUSEPOS pMousePos) { L_INT32 nCount; AnnGetNeighborObjects( pData->hObjectChange, pData->AnnObjectNeighbors, &nCount); AnnSortNeighborObjects(pData->hObjectChange, pData->AnnObjectNeighbors, nCount); RoughLateralSpine_RestrictPoint(pData, pData->hObjectChange); switch (pData->nUserHandleID) { case HANDLE_ID_CP0: L_AnnDefine(pData->AnnObjectNeighbors[0], &pMousePos->pt, ANNDEFINE_BEGINMOVEPOINT); L_AnnDefine(pData->AnnObjectNeighbors[1], &pMousePos->pt, ANNDEFINE_BEGINMOVE); break; case HANDLE_ID_CP1: L_AnnDefine(pData->AnnObjectNeighbors[0], &pMousePos->pt, ANNDEFINE_BEGINMOVEPOINT); L_AnnDefine(pData->AnnObjectNeighbors[2], &pMousePos->pt, ANNDEFINE_BEGINMOVE); break; } } L_VOID RoughLateralSpine_Handle_MouseMove(LPCHILDDATA pData, pANNMOUSEPOS pMousePos) { switch (pData->nUserHandleID) { case HANDLE_ID_CP0: L_AnnDefine(pData->AnnObjectNeighbors[0], &pMousePos->pt, ANNDEFINE_APPEND); L_AnnDefine(pData->AnnObjectNeighbors[1], &pMousePos->pt, ANNDEFINE_APPEND); break; case HANDLE_ID_CP1: L_AnnDefine(pData->AnnObjectNeighbors[0], &pMousePos->pt, ANNDEFINE_APPEND); L_AnnDefine(pData->AnnObjectNeighbors[2], &pMousePos->pt, ANNDEFINE_APPEND); break; } } L_VOID RoughLateralSpine_Handle_LButtonUp(LPCHILDDATA pData, pANNMOUSEPOS pMousePos) { switch (pData->nUserHandleID) { case HANDLE_ID_CP0: L_AnnDefine(pData->AnnObjectNeighbors[0], &pMousePos->pt, ANNDEFINE_END); L_AnnDefine(pData->AnnObjectNeighbors[1], &pMousePos->pt, ANNDEFINE_END); break; case HANDLE_ID_CP1: L_AnnDefine(pData->AnnObjectNeighbors[0], &pMousePos->pt, ANNDEFINE_END); L_AnnDefine(pData->AnnObjectNeighbors[2], &pMousePos->pt, ANNDEFINE_END); break; } MoveHandle(pData->AnnObjectNeighbors[0], pData->nUserHandleID, pMousePos->pt); ClipCursor(&pData->rcOldClip); } //*************** RoughLateralSpine Misc functions L_VOID RoughLateralSpine_ClipCursor(LPCHILDDATA pData, HANNOBJECT hObject, POINT ptStart, L_BOOL bRestore) { L_INT32 nCount; ANNRECT arcBounds; RECT rcBounds; AnnGetNeighborObjects( hObject, pData->AnnObjectNeighbors, &nCount); AnnSortNeighborObjects(hObject, pData->AnnObjectNeighbors, nCount); // Restrict only the box--the line is unrestricted GetBoundingBox(pData->AnnObjectNeighbors, 1, &arcBounds); L_AnnConvert(pData->hContainer, (LPPOINT)&rcBounds, (pANNPOINT)&arcBounds, 2, ANNCONVERT_TO_CLIENT); L_AnnRestrictCursor(pData->hContainer, &rcBounds, &ptStart, &pData->rcOldClip, FALSE); }