/******************************************************************************/ /* T_FHSEL.CPP: IMPLEMENTATION OF THE CFreehandSelectTool CLASS */ /* */ /* */ /******************************************************************************/ /* */ /* Methods in this file */ /* */ /******************************************************************************/ /* */ /******************************************************************************/ #include "stdafx.h" #include "global.h" #include "pbrush.h" #include "pbrusdoc.h" #include "pbrusfrm.h" #include "bmobject.h" #include "imgsuprt.h" #include "imgbrush.h" #include "imgwnd.h" #include "imgwell.h" #include "t_fhsel.h" #ifdef _DEBUG #undef THIS_FILE static CHAR BASED_CODE THIS_FILE[] = __FILE__; #endif IMPLEMENT_DYNAMIC( CFreehandSelectTool, CPolygonTool ) #include "memtrace.h" extern CSelectTool NEAR g_selectTool; CFreehandSelectTool NEAR g_freehandselectTool; /******************************************************************************/ CFreehandSelectTool::CFreehandSelectTool() { m_bIsUndoable = FALSE; m_nCmdID = IDMB_PICKRGNTOOL; m_bCanBePrevTool = FALSE; m_bFilled = FALSE; m_bBorder = FALSE; m_nStrokeWidth = 1; m_pcRgnPoly = &(theImgBrush.m_cRgnPolyFreeHandSel); m_pcRgnPolyBorder = &(theImgBrush.m_cRgnPolyFreeHandSelBorder); } /******************************************************************************/ CFreehandSelectTool::~CFreehandSelectTool() { } /******************************************************************************/ void CFreehandSelectTool::AdjustPointsForZoom(int iZoom) { int iSize = (int)m_cObArrayPoints.GetSize(); CPoint *pcPoint; for (int i = 0; i < iSize; i++) { pcPoint= (CPoint *)m_cObArrayPoints.GetAt(i); pcPoint->x *= iZoom; pcPoint->y *= iZoom; } } /******************************************************************************/ BOOL CFreehandSelectTool::CreatePolyRegion( int iZoom ) { BOOL bRC = TRUE; CPoint *pcPointArray; // cleanup old region if exists if (m_pcRgnPoly->GetSafeHandle()) m_pcRgnPoly->DeleteObject(); // cleanup old region if exists if (m_pcRgnPolyBorder->GetSafeHandle()) m_pcRgnPolyBorder->DeleteObject(); bRC = CopyPointsToMemArray( &pcPointArray, &m_iNumPoints ); if (! bRC) { theApp.SetMemoryEmergency(); return FALSE; } bRC = m_pcRgnPoly->CreatePolygonRgn( pcPointArray, m_iNumPoints, ALTERNATE ); delete [] pcPointArray; if (! bRC) // offset for selection boundary { theApp.SetGdiEmergency(); return FALSE; } m_pcRgnPoly->OffsetRgn( -m_cRectBounding.left, -m_cRectBounding.top ); // // This adjustment appears to be unnecessary. removed it 5/1/1997 // AdjustPointsForZoom( iZoom ); bRC = CopyPointsToMemArray( &pcPointArray, &m_iNumPoints ); if (bRC) { bRC = m_pcRgnPolyBorder->CreatePolygonRgn( pcPointArray, m_iNumPoints, ALTERNATE ); delete [] pcPointArray; if (bRC) // offset for selection boundary m_pcRgnPolyBorder->OffsetRgn( -(m_cRectBounding.left * iZoom), -(m_cRectBounding.top * iZoom) ); } if (! bRC) m_pcRgnPoly->DeleteObject(); return bRC; } /******************************************************************************/ BOOL CFreehandSelectTool::CreatePolyRegion( int iZoom, LPPOINT lpPoints, int iPoints ) { if (! lpPoints || iPoints < 3) return FALSE; DeleteArrayContents(); TRY { CPoint* pPt; for (int i = 0; i < iPoints; i++) { pPt = new CPoint( lpPoints[i] ); m_cObArrayPoints.Add( (CObject *)pPt ); } } CATCH( CMemoryException, e ) { DeleteArrayContents(); theApp.SetMemoryEmergency(); return FALSE; } END_CATCH m_iNumPoints = iPoints; AdjustBoundingRect(); rcPrev = m_cRectBounding; m_bMultPtOpInProgress = FALSE; theImgBrush.m_bMakingSelection = FALSE; theImgBrush.m_bMoveSel = FALSE; theImgBrush.m_bSmearSel = FALSE; if (! CreatePolyRegion( iZoom )) return FALSE; return TRUE; } /******************************************************************************/ BOOL CFreehandSelectTool::ExpandPolyRegion( int iNewSizeX, int iNewSizeY ) { CPoint* pcPointArray; int iNumPts; if (! CopyPointsToMemArray( &pcPointArray, &iNumPts )) return FALSE; int iWidth = m_cRectBounding.Width() + 1; int iHeight = m_cRectBounding.Height() + 1; int iDeltaX = ((iNewSizeX - iWidth ) * 10) / iWidth; int iDeltaY = ((iNewSizeY - iHeight) * 10) / iHeight; CPoint* pPtArray = pcPointArray; int iPts = iNumPts; while (iPts--) { pPtArray->x = (((pPtArray->x * 10) + (pPtArray->x * iDeltaX)) + 5) / 10; pPtArray->y = (((pPtArray->y * 10) + (pPtArray->y * iDeltaY)) + 5) / 10; pPtArray++; } BOOL bReturn = CreatePolyRegion( CImgWnd::GetCurrent()->GetZoom(), pcPointArray, iNumPts ); delete [] pcPointArray; return bReturn; } /******************************************************************************/ /* This routine is called before rendering onto the DC. It basically, calls */ /* the default setup to setup the pen and brush, and then overrides the Pen if*/ /* drawing in progress and drawing without any border. This case is necessary*/ /* since if you do not have a border, you need to see something during the in */ /* progress drawing mode. It uses the inverse (not) of the screen color as */ /* the border in this mode. */ BOOL CFreehandSelectTool::SetupPenBrush(HDC hDC, BOOL bLeftButton, BOOL bSetup, BOOL bCtrlDown) { static int iOldROP2Code; static BOOL bCurrentlySetup = FALSE; m_nStrokeWidth = 1; // override any changes BOOL bRC = CClosedFormTool::SetupPenBrush(hDC, bLeftButton, bSetup, bCtrlDown); // for multipt operations in progress (e.g. drawing outline, not fill yet // if there is no border, use the not of the screen color for the border. // When bMultiptopinprogress == FALSE, final drawing, we will use a null // pen and thus have no border. if (bSetup) { if (bCurrentlySetup) bRC = FALSE; else { bCurrentlySetup = TRUE; iOldROP2Code = SetROP2(hDC, R2_NOT); } } else { if (bCurrentlySetup) { bCurrentlySetup = FALSE; // if no border, restore drawing mode SetROP2(hDC, iOldROP2Code); } else // Error: Cannot Free/cleanup Brush/Pen -- Never allocated. bRC = FALSE; } return bRC; } /******************************************************************************/ /* Call the line's adjustpointsforconstraint member function */ void CFreehandSelectTool::AdjustPointsForConstraint(MTI *pmti) { CClosedFormTool::AdjustPointsForConstraint(pmti); } /******************************************************************************/ // ptDown must be anchor point for our line, not where we did mouse button down void CFreehandSelectTool::PreProcessPoints(MTI *pmti) { CClosedFormTool::PreProcessPoints(pmti); } /***************************************************************************/ void CFreehandSelectTool::OnPaintOptions ( CDC* pDC, const CRect& paintRect, const CRect& optionsRect ) { g_selectTool.OnPaintOptions( pDC, paintRect, optionsRect ); } /******************************************************************************/ void CFreehandSelectTool::OnClickOptions ( CImgToolWnd* pWnd, const CRect& optionsRect, const CPoint& clickPoint ) { g_selectTool.OnClickOptions(pWnd, optionsRect, clickPoint); } /******************************************************************************/ void CFreehandSelectTool::OnStartDrag( CImgWnd* pImgWnd, MTI* pmti ) { HideBrush(); OnActivate( FALSE ); // CommitSelection( TRUE ); pImgWnd->EraseTracker(); theImgBrush.m_bMakingSelection = TRUE; // simulate multipt op in progress, until button up or asked. This will // allow us to draw differently for duration and end. m_bMultPtOpInProgress = TRUE; DeleteArrayContents(); CClosedFormTool::OnStartDrag( pImgWnd, pmti ); } /******************************************************************************/ void CFreehandSelectTool::OnEndDrag( CImgWnd* pImgWnd, MTI* pmti ) { int iZoom = pImgWnd->GetZoom(); theImgBrush.m_bMakingSelection = FALSE; theImgBrush.m_bMoveSel = theImgBrush.m_bSmearSel = FALSE; OnDrag(pImgWnd, pmti); // one last time to refresh display in prep for final render Render( CDC::FromHandle(pImgWnd->m_pImg->hDC), m_cRectBounding, pmti->fLeft, TRUE, pmti->fCtrlDown ); m_iNumPoints = (int)m_cObArrayPoints.GetSize(); if (m_iNumPoints > 2) if (! CreatePolyRegion( iZoom )) return; if (pmti->ptDown.x == pmti->pt.x && pmti->ptDown.y == pmti->pt.y) { if (m_iNumPoints > 3) // 3 is min points. If click down/up get 2 { // must fool selectTool.OnEndDrag to think width of selection is // greater than 0. If 0, thinks selection is done/place it (i.e. // just clicked down/up. We only do this if the end point is the // same as the beginning point. This case will have width=height=0, // but number of points > 2 pmti->pt.x++; pmti->pt.y++; } } pmti->ptDown = m_cRectBounding.TopLeft(); pmti->pt = m_cRectBounding.BottomRight(); g_selectTool.OnEndDrag(pImgWnd, pmti); } /******************************************************************************/ void CFreehandSelectTool::OnDrag( CImgWnd* pImgWnd, MTI* pmti ) { // Must set rcPrev to m_cRectBoundingRect prior to calling SetCurrentPoint // Since SetCurrentPoint will adjust m_cRectBounding, and we want the // previous bounding rect. rcPrev = m_cRectBounding; if (pmti->pt.x > pImgWnd->m_pImg->cxWidth) pmti->pt.x = pImgWnd->m_pImg->cxWidth; if (pmti->pt.y > pImgWnd->m_pImg->cyHeight) pmti->pt.y = pImgWnd->m_pImg->cyHeight; if (pmti->pt.x < 0) pmti->pt.x = 0; if (pmti->pt.y < 0) pmti->pt.y = 0; TRY { AddPoint(pmti->pt); } CATCH(CMemoryException,e) { theApp.SetMemoryEmergency(); return; } END_CATCH CClosedFormTool::OnDrag(pImgWnd, pmti); } /******************************************************************************/ void CFreehandSelectTool::OnCancel(CImgWnd* pImgWnd) { // We were not selecting or dragging, just cancel the select tool... CommitSelection( TRUE ); //render one last time to turn off/invert the line if any drawn if (theImgBrush.m_bMakingSelection) { Render( CDC::FromHandle( pImgWnd->m_pImg->hDC ), m_cRectBounding, TRUE, TRUE, FALSE ); } theImgBrush.TopLeftHandle(); g_bCustomBrush = FALSE; theImgBrush.m_pImg = NULL; theImgBrush.m_bMoveSel = FALSE; theImgBrush.m_bSmearSel = FALSE; theImgBrush.m_bMakingSelection = FALSE; InvalImgRect( pImgWnd->m_pImg, NULL ); DeleteArrayContents(); CPolygonTool::OnCancel(pImgWnd); } /***************************************************************************/ BOOL CFreehandSelectTool::IsToolModal(void) { if (theImgBrush.m_pImg) { return(TRUE); } return(CPolygonTool::IsToolModal()); } /******************************************************************************/ void CFreehandSelectTool::OnActivate(BOOL bActivate) { g_selectTool.OnActivate(bActivate); } /******************************************************************************/ /* this class really isn't a multipt operation, but is derived from one thus */ /* we can always end the multipt operation if anyone asks */ BOOL CFreehandSelectTool::CanEndMultiptOperation(MTI* pmti ) { m_bMultPtOpInProgress = FALSE; return (CClosedFormTool::CanEndMultiptOperation(pmti)); } /******************************************************************************/