442 lines
13 KiB
C++
442 lines
13 KiB
C++
/******************************************************************************/
|
||
/* 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));
|
||
}
|
||
|
||
/******************************************************************************/
|
||
|