//SpineMeasure.c #include "SpineMeasure.h" #include "annotate.h" #include "utils.h" #include "limits.h" // HANDLE_ID_HORIZONTAL_TOP // ********************************* // * * * // * * * // HANDLE_ID_VERTICAL_LEFT * * * HANDLE_ID_VERTICAL_RIGHT // * * * // * * * // ********************************* // HANDLE_ID_HORIZONTAL_BOTTOM //************************************************************************************** // // Functions for SpineMeasure // //************************************************************************************* L_VOID SpineMeasure_UpdateHandles(HANNOBJECT hObject) { L_UINT uCount; L_INT nRet; ANNPOINT AnnPoints[4]; L_AnnGetPoints(hObject, AnnPoints); nRet = L_AnnGetUserHandles(hObject, NULL, &uCount); if ((nRet == SUCCESS) && (uCount)) { //L_AnnDeleteHandle(hObject, -1); //delete all handles, and add them back SpineMeasure_AddUserHandles(hObject, AnnPoints); } } // SpineMeasure_AddUserHandles--adds handles for AP SPine Measure Annotation L_VOID SpineMeasure_AddUserHandles(HANNOBJECT hObject, pANNPOINT pAnnPoints) { ANNHANDLE AnnHandle; ANNHANDLE FourAnnHandles[4]; L_UINT uCount; L_UINT uFlags; L_AnnGetUserHandles(hObject, NULL, &uCount); if (uCount == 4) { uFlags = ANNHANDLE_LOCATION | ANNHANDLE_CONTAINER_COORDINATES; L_AnnGetUserHandles(hObject, FourAnnHandles, &uCount); FourAnnHandles[0].aptContainer.x = (pAnnPoints[0].x + pAnnPoints[1].x) / 2; FourAnnHandles[0].aptContainer.y = (pAnnPoints[0].y + pAnnPoints[1].y) / 2; FourAnnHandles[0].uFlags =uFlags; L_AnnChangeUserHandle(hObject, 0, FourAnnHandles + 0); FourAnnHandles[1].aptContainer.x = (pAnnPoints[1].x + pAnnPoints[2].x) / 2; FourAnnHandles[1].aptContainer.y = (pAnnPoints[1].y + pAnnPoints[2].y) / 2; FourAnnHandles[1].uFlags =uFlags; L_AnnChangeUserHandle(hObject, 1, FourAnnHandles + 1); FourAnnHandles[2].aptContainer.x = (pAnnPoints[2].x + pAnnPoints[3].x) / 2; FourAnnHandles[2].aptContainer.y = (pAnnPoints[2].y + pAnnPoints[3].y) / 2; FourAnnHandles[2].uFlags =uFlags; L_AnnChangeUserHandle(hObject, 2, FourAnnHandles + 2); FourAnnHandles[3].aptContainer.x = (pAnnPoints[3].x + pAnnPoints[0].x) / 2; FourAnnHandles[3].aptContainer.y = (pAnnPoints[3].y + pAnnPoints[0].y) / 2; FourAnnHandles[3].uFlags =uFlags; L_AnnChangeUserHandle(hObject, 3, FourAnnHandles + 3); } else { uFlags = ANNHANDLE_LOCATION | ANNHANDLE_CONTAINER_COORDINATES | ANNHANDLE_ID | ANNHANDLE_PEN_COLOR | ANNHANDLE_FILL_COLOR | ANNHANDLE_SHAPE; AnnHandle.uStructSize = sizeof(ANNHANDLE); AnnHandle.nShape = ANNHANDLE_SHAPE_CIRCLE; AnnHandle.crPen = RGB(0,0,0); AnnHandle.uFlags = uFlags; AnnHandle.aptContainer.x = (pAnnPoints[0].x + pAnnPoints[1].x) / 2; AnnHandle.aptContainer.y = (pAnnPoints[0].y + pAnnPoints[1].y) / 2; AnnHandle.crFill = RGB(0,0,0); AnnHandle.hCursor= hCursorHorizontalResize; //LoadCursor(NULL, IDC_SIZEALL); AnnHandle.nID = HANDLE_ID_VERTICAL_LEFT; L_AnnAddUserHandle(hObject, &AnnHandle); AnnHandle.aptContainer.x = (pAnnPoints[1].x + pAnnPoints[2].x) / 2; AnnHandle.aptContainer.y = (pAnnPoints[1].y + pAnnPoints[2].y) / 2; AnnHandle.crFill = RGB(128,128,128); AnnHandle.hCursor= hCursorRotate; //LoadCursor(NULL, IDC_SIZENS); AnnHandle.nID = HANDLE_ID_HORIZONTAL_BOTTOM; L_AnnAddUserHandle(hObject, &AnnHandle); AnnHandle.aptContainer.x = (pAnnPoints[2].x + pAnnPoints[3].x) / 2; AnnHandle.aptContainer.y = (pAnnPoints[2].y + pAnnPoints[3].y) / 2; AnnHandle.crFill = RGB(255,0,0); AnnHandle.hCursor= hCursorHorizontalResize;//LoadCursor(NULL, IDC_SIZEALL); AnnHandle.nID = HANDLE_ID_VERTICAL_RIGHT; L_AnnAddUserHandle(hObject, &AnnHandle); AnnHandle.aptContainer.x = (pAnnPoints[3].x + pAnnPoints[0].x) / 2; AnnHandle.aptContainer.y = (pAnnPoints[3].y + pAnnPoints[0].y) / 2; AnnHandle.crFill = RGB(255,255,0); AnnHandle.hCursor= hCursorRotate; AnnHandle.nID = HANDLE_ID_HORIZONTAL_TOP; L_AnnAddUserHandle(hObject, &AnnHandle); } } // SpineMeasure_UpdateLine--draws the line for the AP SPine Measure annotation L_VOID SpineMeasure_UpdateLine(HANNOBJECT hRect, HANNOBJECT hLine) { ANNPOINT apt[2]; GetHandleInfo(hRect, HANDLE_ID_HORIZONTAL_TOP, NULL, apt+0, NULL); GetHandleInfo(hRect, HANDLE_ID_HORIZONTAL_BOTTOM, NULL, apt+1, NULL); L_AnnSetPoints(hLine, apt, 2); HideDefaultHandles(hLine); L_AnnSetVisible(hLine, TRUE, 0, NULL); AnnSetID(hLine, ANNTOOL_AP_SPINE_MEASURE, 1); } // L_VOID SpineMeasure_Handle_LButtonDown(LPCHILDDATA pData, pANNMOUSEPOS pMousePos) { RECT rcClip; L_INT32 nCount; ANNRECT arcContainer; AnnGetNeighborObjects( pData->hObjectChange, pData->AnnObjectNeighbors, &nCount); AnnSortNeighborObjects(pData->hObjectChange, pData->AnnObjectNeighbors, nCount); switch (pData->nUserHandleID) { case HANDLE_ID_VERTICAL_LEFT: case HANDLE_ID_VERTICAL_RIGHT: pData->ptStart = pMousePos->pt; L_AnnDefine(pData->hObjectChange, &pMousePos->pt, ANNDEFINE_BEGINRESIZE); L_AnnDefine(pData->AnnObjectNeighbors[1], &pMousePos->pt, ANNDEFINE_BEGINMOVE); break; case HANDLE_ID_HORIZONTAL_TOP: { ANNPOINT aptBottom; ANNPOINT aptTop; POINT ptBottom; GetClipCursor(&pData->rcOldClip); rcClip = pData->rcOldClip; GetHandleInfo(pData->hObjectChange, HANDLE_ID_HORIZONTAL_TOP, NULL, &aptTop, NULL); GetHandleInfo(pData->hObjectChange, HANDLE_ID_HORIZONTAL_BOTTOM, &ptBottom, &aptBottom, NULL); L_AnnGetRect(pData->hContainer, &arcContainer, NULL); L_AnnConvert(pData->hContainer, (LPPOINT)&rcClip, (pANNPOINT)&arcContainer, 2, ANNCONVERT_TO_CLIENT); rcClip.bottom = ptBottom.y + 1; L_AnnRestrictCursor(pData->hContainer, &rcClip, NULL, NULL, FALSE); L_AnnDefine2(pData->hObjectChange, &aptBottom, ANNDEFINE_SETANCHORPOINT); L_AnnDefine2(pData->hObjectChange, &aptTop, ANNDEFINE_BEGINMOVEPOINT); L_AnnDefine(pData->AnnObjectNeighbors[1], &pMousePos->pt, ANNDEFINE_BEGINMOVEPOINT); } break; case HANDLE_ID_HORIZONTAL_BOTTOM: { ANNPOINT aptBottom; ANNPOINT aptTop; POINT ptTop; GetClipCursor(&pData->rcOldClip); rcClip = pData->rcOldClip; GetHandleInfo(pData->hObjectChange, HANDLE_ID_HORIZONTAL_TOP, &ptTop, &aptTop, NULL); GetHandleInfo(pData->hObjectChange, HANDLE_ID_HORIZONTAL_BOTTOM, NULL, &aptBottom, NULL); L_AnnGetRect(pData->hContainer, &arcContainer, NULL); L_AnnConvert(pData->hContainer, (LPPOINT)&rcClip, (pANNPOINT)&arcContainer, 2, ANNCONVERT_TO_CLIENT); rcClip.top = ptTop.y; L_AnnRestrictCursor(pData->hContainer, &rcClip, NULL, &pData->rcOldClip, FALSE); L_AnnDefine2(pData->hObjectChange, &aptTop, ANNDEFINE_SETANCHORPOINT); L_AnnDefine2(pData->hObjectChange, &aptBottom, ANNDEFINE_BEGINMOVEPOINT); L_AnnDefine(pData->AnnObjectNeighbors[1], &pMousePos->pt, ANNDEFINE_BEGINMOVEPOINT); } break; } } POINT SpineMeasure_AdjustVerticalHandle(LPCHILDDATA pData, POINT ptMoveOriginal, LPPOINT pptLineAdjust) { POINT ptMove; L_DOUBLE dDistance; ANNPOINT aptMove; L_DOUBLE dAngle; ANNPOINT aptAnchor; L_AnnGetRotateAngle(pData->hObjectChange, &dAngle); aptAnchor.x = pData->pt0.x; aptAnchor.y = pData->pt0.y; aptMove.x = ptMoveOriginal.x; aptMove.y = ptMoveOriginal.y; L_AnnAdjustPoint(&aptAnchor, &aptMove, dAngle, ANNADJUST_HORIZONTAL); ptMove.x = (LONG)aptMove.x; ptMove.y = (LONG)aptMove.y; dDistance = DistanceUserHandleToLine( pData->hObjectChange, pData->nUserHandleID==HANDLE_ID_VERTICAL_LEFT ? HANDLE_ID_VERTICAL_RIGHT : HANDLE_ID_VERTICAL_LEFT, ptMove ); if (dDistance < MIN_WIDTH) { // STATE_TOO_CLOSE; ptMove = PointAtDistanceToOppositeLine( pData->hObjectChange, pData->nUserHandleID==HANDLE_ID_VERTICAL_LEFT ? HANDLE_ID_VERTICAL_RIGHT : HANDLE_ID_VERTICAL_LEFT, MIN_WIDTH, pData->ptStart); } else if (dDistance > MAX_WIDTH) { // STATE_TOO_FAR; ptMove = PointAtDistanceToOppositeLine( pData->hObjectChange, pData->nUserHandleID==HANDLE_ID_VERTICAL_LEFT ? HANDLE_ID_VERTICAL_RIGHT : HANDLE_ID_VERTICAL_LEFT, MAX_WIDTH, pData->ptStart); } if (pptLineAdjust) { POINT pt; L_INT32 dx, dy; pt = ptMove; dx = (ptMove.x - (L_INT32)aptAnchor.x)/2; dy = (ptMove.y - (L_INT32)aptAnchor.y)/2; pt.x = (LONG)(aptAnchor.x + dx); pt.y = (LONG)(aptAnchor.y + dy); *pptLineAdjust = pt; } return ptMove; } POINT SpineMeasure_AdjustHorizontalHandle(LPCHILDDATA pData, POINT ptMoveOriginal) { POINT ptMove; L_DOUBLE dDistance; ptMove = ptMoveOriginal; dDistance = DistanceToUserHandle(pData->hObjectChange, pData->nUserHandleID==HANDLE_ID_HORIZONTAL_TOP ? HANDLE_ID_HORIZONTAL_BOTTOM : HANDLE_ID_HORIZONTAL_TOP, ptMoveOriginal); if (dDistance < MIN_HEIGHT) { // STATE_TOO_CLOSE; ptMove = PointAtDistanceToUserHandle( pData->hObjectChange, pData->nUserHandleID==HANDLE_ID_HORIZONTAL_TOP ? HANDLE_ID_HORIZONTAL_BOTTOM : HANDLE_ID_HORIZONTAL_TOP, MIN_HEIGHT, ptMove); } else if (dDistance > MAX_HEIGHT) { // STATE_TOO_FAR; ptMove = PointAtDistanceToUserHandle( pData->hObjectChange, pData->nUserHandleID==HANDLE_ID_HORIZONTAL_TOP ? HANDLE_ID_HORIZONTAL_BOTTOM : HANDLE_ID_HORIZONTAL_TOP, MAX_HEIGHT, ptMove); } return ptMove; } L_VOID SpineMeasure_Handle_MouseMove(LPCHILDDATA pData, pANNMOUSEPOS pMousePos) { POINT ptMove; switch (pData->nUserHandleID) { case HANDLE_ID_VERTICAL_RIGHT: case HANDLE_ID_VERTICAL_LEFT: { POINT ptLineAdjust; ptMove = SpineMeasure_AdjustVerticalHandle( pData, pMousePos->pt, &ptLineAdjust); L_AnnDefine(pData->hObjectChange, &ptMove, ANNDEFINE_APPEND); L_AnnDefine(pData->AnnObjectNeighbors[1], &ptLineAdjust, ANNDEFINE_APPEND); } break; case HANDLE_ID_HORIZONTAL_BOTTOM: case HANDLE_ID_HORIZONTAL_TOP: ptMove = SpineMeasure_AdjustHorizontalHandle( pData, pMousePos->pt); L_AnnDefine(pData->hObjectChange, &ptMove, ANNDEFINE_APPEND); L_AnnDefine(pData->AnnObjectNeighbors[1], &ptMove, ANNDEFINE_APPEND); break; } pMousePos->fUpdatePos = FALSE; } L_VOID SpineMeasure_Handle_LButtonUp(LPCHILDDATA pData, pANNMOUSEPOS pMousePos) { POINT ptMove, ptLineAdjust; switch(pData->nUserHandleID) { case HANDLE_ID_HORIZONTAL_BOTTOM: case HANDLE_ID_HORIZONTAL_TOP: ClipCursor(NULL); ptMove = SpineMeasure_AdjustHorizontalHandle( pData, pMousePos->pt); L_AnnDefine(pData->hObjectChange, &ptMove, ANNDEFINE_END); L_AnnDefine(pData->AnnObjectNeighbors[1], &ptMove, ANNDEFINE_END); break; case HANDLE_ID_VERTICAL_LEFT: case HANDLE_ID_VERTICAL_RIGHT: ptMove = SpineMeasure_AdjustVerticalHandle( pData, pMousePos->pt, &ptLineAdjust); L_AnnDefine(pData->hObjectChange, &ptMove, ANNDEFINE_END); L_AnnDefine(pData->AnnObjectNeighbors[1], &ptLineAdjust, ANNDEFINE_END); break; } SpineMeasure_UpdateHandles(pData->hObjectChange); SpineMeasure_UpdateLine(pData->hObjectChange, pData->AnnObjectNeighbors[1]); } //*************** SpineMeasure Create functions L_VOID SpineMeasure_LButtonDown(HWND hWnd, LPCHILDDATA pData) { pData->ObjectSpineMeasure.bLineAdjust = FALSE; L_AnnAddUndoNode(pData->hAutomation); L_AnnCreateItem(pData->hContainer, ANNOBJECT_RECT, TRUE, &pData->ObjectSpineMeasure.hRect); AnnSetID(pData->ObjectSpineMeasure.hRect, ANNTOOL_AP_SPINE_MEASURE, 0); L_AnnDefine(pData->ObjectSpineMeasure.hRect, &pData->ptStart, ANNDEFINE_BEGINSET); L_AnnCreateItem(pData->hContainer, ANNOBJECT_LINE, TRUE, &pData->ObjectSpineMeasure.hLine); AnnSetID(pData->ObjectSpineMeasure.hLine, ANNTOOL_AP_SPINE_MEASURE, 1); pData->fCapture = TRUE; L_AnnDefine(pData->ObjectSpineMeasure.hLine, &pData->ptStart, ANNDEFINE_BEGINSET); L_AnnRestrictCursor(pData->hContainer, NULL, NULL, &pData->rcOldClip,TRUE); } L_VOID SpineMeasure_MouseMove(LPCHILDDATA pData) { L_AnnDefine(pData->ObjectSpineMeasure.hRect, &pData->ptMove, ANNDEFINE_APPEND); pData->ObjectSpineMeasure.bLineAdjust = TRUE; L_AnnDefine(pData->ObjectSpineMeasure.hLine, &pData->ptStart, ANNDEFINE_APPEND); pData->ObjectSpineMeasure.bLineAdjust = FALSE; } L_VOID SpineMeasure_LButtonUp(LPCHILDDATA pData, L_UINT uTool) { ANNPOINT AnnPoints[4]; HANNOBJECT hLine; // Destroy the line L_AnnDefine(pData->ObjectSpineMeasure.hLine, &pData->ptEnd, ANNDEFINE_END); L_AnnRemove(pData->ObjectSpineMeasure.hLine); L_AnnDestroy(pData->ObjectSpineMeasure.hLine, 0); // Finish creating the rectangle L_AnnDefine(pData->ObjectSpineMeasure.hRect, &pData->ptEnd, ANNDEFINE_END); HideDefaultHandles(pData->ObjectSpineMeasure.hRect); L_AnnGetPoints(pData->ObjectSpineMeasure.hRect, AnnPoints); SpineMeasure_AddUserHandles(pData->ObjectSpineMeasure.hRect, AnnPoints); L_AnnSetSelected(pData->ObjectSpineMeasure.hRect, TRUE, 0); // Create the line L_AnnCreateItem(pData->hContainer, ANNOBJECT_LINE, FALSE, &hLine); L_AnnSendToBack(hLine); SpineMeasure_UpdateLine(pData->ObjectSpineMeasure.hRect, hLine); L_AnnSetSelected(hLine, TRUE, 0); HideDefaultHandles(hLine); // 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); AnnSetID(pData->ObjectSpineMeasure.hRect, uTool, 0); DebugClipCursor(&pData->rcOldClip); } //*************** SpineMeasure Misc functions L_VOID SpineMeasure_Hilight(LPCHILDDATA pData, pANNHILIGHT pAnnHilight) { L_UINT uType; L_AnnGetType(pAnnHilight->hObject, &uType); if (pData->ObjectSpineMeasure.bLineAdjust && (uType == ANNOBJECT_LINE)) { if (pAnnHilight->bRemoveHilight) { pAnnHilight->ppts[0] = pData->ObjectSpineMeasure.ptPrevHilight[0]; pAnnHilight->ppts[1] = pData->ObjectSpineMeasure.ptPrevHilight[1]; } else { pAnnHilight->ppts[0].x = (pData->ptStart.x + pData->ptMove.x) / 2; pAnnHilight->ppts[1].x = pAnnHilight->ppts[0].x; pAnnHilight->ppts[0].y = pData->ptStart.y; pAnnHilight->ppts[1].y = pData->ptMove.y; } pData->ObjectSpineMeasure.ptPrevHilight[0] = pAnnHilight->ppts[0]; pData->ObjectSpineMeasure.ptPrevHilight[1] = pAnnHilight->ppts[1]; } }