reman3/Rayman_X/cpa/tempgrp/ITF/cpadd.cpp

447 lines
12 KiB
C++

#include "stdafx.h"
#ifdef ACTIVE_EDITOR
#include "acp_base.h"
#include <sys/timeb.h>
#include "itf/CPAProj.hpp"
#include "itf/DEVMul3D.hpp"
#include "itf/CPADD.hpp"
#include "itf/CPARes.h"
// For rectangles
static int gs_iNumOfRects = 0;
typedef struct DD_tdstRect_
{
RECT stRect;
HWND hWnd;
} DD_tdstRect;
#define DD_C_MaxRects 50
static DD_tdstRect gs_a_stRects[DD_C_MaxRects];
// for timer
UINT gs_uiTimer;
UINT gs_uiElapseScroll = 500;
int gs_iRect = -1;
//==================================================================
// REFERENCES
//==================================================================
// Search a reference to a window in array of all references
BOOL DD_bSearchReference(HWND hWnd, char *p_szName, UINT uiDataType, BOOL *p_bCopy)
{
int iIndex;
for(iIndex = 0; iIndex < M_GetMainApp()->m_iNumRef; iIndex++)
{
if
(
(M_GetMainApp()->m_a_WndRef[iIndex].hWnd == hWnd)
&& (!strcmpi(p_szName, M_GetMainApp()->m_a_WndRef[iIndex].p_szEditorName))
&& (M_GetMainApp()->m_a_WndRef[iIndex].uiDataType == uiDataType)
)
{
*p_bCopy = M_GetMainApp()->m_a_WndRef[iIndex].bCopyOnly;
return TRUE;
}
}
return FALSE;
}
// Add a reference to a window that can receive a dragdrop object
tdeDDError DD_eAddReference(HWND hWnd, char *p_szName, UINT uiDataType, BOOL bCopy)
{
BOOL bTemp;
// Too much references already define
if(M_GetMainApp()->m_iNumRef == C_ucMaxCWndRef)
return E_DDERR_TooMuchRef;
// Reference always exists
if(DD_bSearchReference(hWnd, p_szName, uiDataType, &bTemp))
return E_DDERR_None;
// Add reference
M_GetMainApp()->m_a_WndRef[M_GetMainApp()->m_iNumRef].hWnd = hWnd;
M_GetMainApp()->m_a_WndRef[M_GetMainApp()->m_iNumRef].p_szEditorName = p_szName;
M_GetMainApp()->m_a_WndRef[M_GetMainApp()->m_iNumRef].uiDataType = uiDataType;
M_GetMainApp()->m_a_WndRef[M_GetMainApp()->m_iNumRef++].bCopyOnly = bCopy;
return E_DDERR_None;
}
// Delete a reference to a window (all types)
tdeDDError DD_eDelReference(HWND hWnd)
{
int iIndex;
BOOL bOk = FALSE;
for(iIndex = 0; iIndex < M_GetMainApp()->m_iNumRef; iIndex++)
{
if(M_GetMainApp()->m_a_WndRef[iIndex].hWnd == hWnd)
{
memmove(&M_GetMainApp()->m_a_WndRef[iIndex], &M_GetMainApp()->m_a_WndRef[iIndex+1], M_GetMainApp()->m_iNumRef - iIndex);
M_GetMainApp()->m_iNumRef--;
bOk = TRUE;
}
}
if(bOk)
return E_DDERR_None;
else
return E_DDERR_UnknownRef;
}
// Delete a reference to a window with a special type
tdeDDError DD_eDelReferenceType(HWND hWnd, char *p_szName, UINT uiDataType)
{
int iIndex;
for(iIndex = 0; iIndex < M_GetMainApp()->m_iNumRef; iIndex++)
{
if
(
(M_GetMainApp()->m_a_WndRef[iIndex].hWnd == hWnd)
&& (!strcmpi(p_szName, M_GetMainApp()->m_a_WndRef[iIndex].p_szEditorName))
&& (M_GetMainApp()->m_a_WndRef[iIndex].uiDataType == uiDataType)
)
{
memmove(&M_GetMainApp()->m_a_WndRef[iIndex], &M_GetMainApp()->m_a_WndRef[iIndex+1], M_GetMainApp()->m_iNumRef - iIndex);
M_GetMainApp()->m_iNumRef--;
return E_DDERR_None;
}
}
return E_DDERR_UnknownRef;
}
// Delete all references
void DD_vDelAllReferences(void)
{
M_GetMainApp()->m_iNumRef = 0;
}
//==================================================================
// Drag & Drop
//==================================================================
// Determins what type of mouse pointer must be drawn regardless to window
// under mouse.
// Set M_GetMainApp()->m_bCanDrop global variable.
void DD_vCanDrop(HWND hWnd, char *p_szEditorName, UINT uiDataType)
{
HCURSOR hcursor;
BOOL bCopy;
// Is Window reference ?
if(hWnd && (DD_bSearchReference(hWnd, p_szEditorName, uiDataType, &bCopy)))
{
M_GetMainApp()->m_bCanDrop = TRUE;
// Copy if CONTROL key is pressed or if window only accept copy objects
if(M_GetMainApp()->m_bControl || bCopy)
{
hcursor = AfxGetApp()->LoadCursor(CPA_IDC_DRAGCOPY);
M_GetMainApp()->m_bCopy = TRUE;
}
else
{
hcursor = AfxGetApp()->LoadCursor(CPA_IDC_DRAGMOVE);
M_GetMainApp()->m_bCopy = FALSE;
}
}
else
{
M_GetMainApp()->m_bCanDrop = FALSE;
M_GetMainApp()->m_bCopy = FALSE;
hcursor = AfxGetApp()->LoadCursor(CPA_IDC_DRAGNONE);
}
::SetCursor(hcursor);
}
// Test if p_Wnd is loosing or gaining the focus of drag & drop
// That function is call only if cursor pos has changed
void DD_vDeterminsFocus(HWND hWnd, DD_Object *p_stDDObject)
{
if (hWnd != M_GetMainApp()->m_LastFocusWnd)
{
// Send a loosing focus message to last window
if(M_GetMainApp()->m_LastFocusWnd)
::SendMessage(M_GetMainApp()->m_LastFocusWnd, WM_DRAGDROP_LOOSEFOCUS, 0, (LPARAM) p_stDDObject);
// If there's a new window that accept drop, we send a message to it
if(hWnd && M_GetMainApp()->m_bCanDrop)
::SendMessage(hWnd, WM_DRAGDROP_GAINFOCUS, 0, (LPARAM) p_stDDObject);
}
else if (hWnd)
{
// Mouse move in the same window than last one
::SendMessage(hWnd, WM_DRAGDROP_MOVE, 0, (LPARAM) p_stDDObject);
}
// Last focus window is now new one
M_GetMainApp()->m_LastFocusWnd = hWnd;
}
// Get mouse position with a LPARAM parameter
// Set m_stMousePos with current value of mouse position
void DD_vGetMousePos(LPARAM lParam, DD_Object *p_stDDObject)
{
GetCursorPos(&M_GetMainApp()->m_stMousePos);
/* M_GetMainApp()->m_stMousePos.x = LOWORD(lParam);
M_GetMainApp()->m_stMousePos.y = HIWORD(lParam);
p_stDDObject->fn_p_stGetOwner()->ClientToScreen(&M_GetMainApp()->m_stMousePos);*/
p_stDDObject->m_stMousePos.x = M_GetMainApp()->m_stMousePos.x;
p_stDDObject->m_stMousePos.y = M_GetMainApp()->m_stMousePos.y;
}
// Finish a drag & drop operation
// Send a message to current window if it accepts drag & drop
// Restore mouse cursor
void DD_vFinish(DD_Object *p_stDDObject)
{
// Send a end of drag & drop message to current window if it's possible, else
// send a loose focus
if(M_GetMainApp()->m_bCanDrop)
::SendMessage(M_GetMainApp()->m_LastFocusWnd, WM_DRAGDROP_END, (WPARAM) M_GetMainApp()->m_bCopy, (LPARAM) p_stDDObject);
else
::SendMessage(M_GetMainApp()->m_LastFocusWnd, WM_DRAGDROP_LOOSEFOCUS, 0, (LPARAM) p_stDDObject);
// Restore initial mouse cursor
::SetCursor(M_GetMainApp()->m_hFirstCursor);
}
// Register a special rectangle
void DD_vRegisterRect(RECT *p_stRect, HWND hWnd)
{
if(gs_iNumOfRects == DD_C_MaxRects)
return;
memcpy(&gs_a_stRects[gs_iNumOfRects].stRect, p_stRect, sizeof(RECT));
gs_a_stRects[gs_iNumOfRects++].hWnd = hWnd;
}
// change timer elapse time
void DD_vSetScrollTime( UINT uiTime )
{
gs_uiElapseScroll = uiTime;
}
// Determins if mouse is in a rect
int fn_iIsInRect(void)
{
int i;
for(i = 0; i < gs_iNumOfRects; i++)
{
if(gs_a_stRects[i].hWnd == M_GetMainApp()->m_LastFocusWnd)
{
POINT pt;
RECT *r = &gs_a_stRects[i].stRect;
GetCursorPos(&pt);
if((pt.x >= r->left ) && (pt.x <= r->right) && (pt.y >= r->top) && (pt.y <= r->bottom))
return i;
}
}
return gs_iNumOfRects;
}
// Treat registered rectangles
void fn_vTreatRects(DD_Object *p_stDDObject)
{
int iRes;
iRes = fn_iIsInRect();
if(iRes < gs_iNumOfRects)
{
if (gs_iRect == -1)
{
gs_uiTimer = SetTimer(NULL, 1, gs_uiElapseScroll, NULL );
gs_iRect = iRes;
}
}
else
{
if (gs_iRect != -1)
{
KillTimer( NULL, gs_uiTimer );
gs_iRect = -1;
}
}
}
// Begin a drag & drop operation
// p_Rect : Rect to begin drag & drop
// p_stObject : Object to transmit
HWND DD_hBeginDragDrop(RECT *p_Rect, DD_Object *p_stDDObject)
{
BOOL bOutOfRect = FALSE;
BOOL bEndOfLoop = FALSE;
BOOL bCanDispatch;
MSG stMsg;
// Inits
//------
M_GetMainApp()->m_bCanDrop = FALSE;
M_GetMainApp()->m_bCopy = FALSE;
M_GetMainApp()->m_bControl = FALSE;
M_GetMainApp()->m_hFirstCursor = ::GetCursor();
// Wait mouse to go out of first rect area
//----------------------------------------
while (bEndOfLoop == FALSE)
{
::GetMessage(&stMsg, NULL, 0, 0);
switch(stMsg.message)
{
case WM_MOUSEMOVE:
DD_vGetMousePos(stMsg.lParam, p_stDDObject);
if (!::PtInRect(p_Rect, M_GetMainApp()->m_stMousePos))
{
bOutOfRect = TRUE;
bEndOfLoop = TRUE;
break;
}
break;
case WM_LBUTTONUP:
bEndOfLoop = TRUE;
break;
}
::TranslateMessage(&stMsg);
::DispatchMessage(&stMsg);
}
// A drag & drop is beginnig if bOutOfRect is set to TRUE
//-------------------------------------------------------
if (bOutOfRect)
{
// Source window capture mouse
//----------------------------
ASSERT(p_stDDObject->fn_p_stGetOwner() != NULL);
p_stDDObject->m_p_oGrabCaptureFor(p_stDDObject->fn_p_stGetOwner());
bEndOfLoop = FALSE;
// The last wnd under mouse is window that owns object
M_GetMainApp()->m_LastFocusWnd = p_stDDObject->fn_p_stGetOwner()->GetSafeHwnd();
while(bEndOfLoop == FALSE)
{
HWND hWndUnder; // Current window under mouse
::GetMessage(&stMsg, NULL, 0, 0);
bCanDispatch = TRUE; // Can dispatch messages ?
switch(stMsg.message)
{
case WM_TIMER:
if (stMsg.wParam == gs_uiTimer)
{
// we are in a scroll rect, send DRAGDROP_SCROLL message
::SendMessage(M_GetMainApp()->m_LastFocusWnd, WM_DRAGDROP_SCROLL, 0, (LPARAM) &gs_a_stRects[gs_iRect].stRect);
// Don't dispatch the message
bCanDispatch = FALSE;
}
break;
case WM_MOUSEMOVE:
// Coords of mouse
DD_vGetMousePos(stMsg.lParam, p_stDDObject);
// Get window under mouse
hWndUnder = WindowFromPoint(M_GetMainApp()->m_stMousePos);
// specific for 2nd screen
if (M_GetMainApp()->GetInterface()->fn_bGetAutomaticSwap())
{
// get active device & viewport
DEV_MultiDevice3D * pMulti = (DEV_MultiDevice3D *) M_GetMainDevice2();
DEV_ViewPort3D * pViewport = (DEV_ViewPort3D *) M_GetActiveViewport(pMulti);
// call this function to detect swap
pViewport->DetectMouseSwap();
// update active window
if (!M_GetMainApp()->m_bCursorInFirstScreen)
hWndUnder = pViewport->GetSafeHwnd();
else if (hWndUnder == pViewport->GetSafeHwnd())
hWndUnder = NULL;
}
// Window under mouse accept drag & drop ?
DD_vCanDrop(hWndUnder, p_stDDObject->fn_p_szGetEditorName(), p_stDDObject->fn_uiGetDataType());
// Treat focus messages
DD_vDeterminsFocus(hWndUnder, p_stDDObject);
// Don't dispatch message
bCanDispatch = FALSE;
break;
case WM_RBUTTONDOWN:
M_GetMainApp()->m_bCanDrop = FALSE;
DD_vFinish(p_stDDObject);
bEndOfLoop = TRUE;
// Don't dispatch message
bCanDispatch = FALSE;
break;
case WM_LBUTTONUP:
DD_vFinish(p_stDDObject);
bEndOfLoop = TRUE;
// Don't dispatch message
bCanDispatch = FALSE;
break;
// For copying object instead of moving it
case WM_KEYDOWN:
if(stMsg.wParam == VK_CONTROL)
{
M_GetMainApp()->m_bControl = TRUE;
// To redraw mouse cursor
DD_vCanDrop(M_GetMainApp()->m_LastFocusWnd, p_stDDObject->fn_p_szGetEditorName(), p_stDDObject->fn_uiGetDataType());
// Don't dispatch message
bCanDispatch = FALSE;
}
break;
case WM_KEYUP:
if(stMsg.wParam == VK_CONTROL)
{
M_GetMainApp()->m_bControl = FALSE;
DD_vCanDrop(M_GetMainApp()->m_LastFocusWnd, p_stDDObject->fn_p_szGetEditorName(), p_stDDObject->fn_uiGetDataType());
// Don't dispatch message
bCanDispatch = FALSE;
}
break;
}
// Can we dispatch message ?
if(bCanDispatch)
{
::TranslateMessage(&stMsg);
::DispatchMessage(&stMsg);
}
// Treat registered rectangles
if(bEndOfLoop == FALSE)
fn_vTreatRects(p_stDDObject);
}
// We restore mouse capture
//-------------------------
p_stDDObject->m_p_oSurrenderCapture();
}
// No rects
gs_iNumOfRects = 0;
// set elapse time to default value
gs_uiElapseScroll = 500;
// kill timer if still in a rectangle
if (gs_iRect != -1)
{
KillTimer( NULL, gs_uiTimer );
gs_iRect = -1;
}
// Return handle of window that accepted Drag & Drop
if(M_GetMainApp()->m_bCanDrop)
return M_GetMainApp()->m_LastFocusWnd;
else
return NULL;
}
#endif // ACTIVE_EDITOR