dragmgr.cpp

Go to the documentation of this file.
00001 // $Id: dragmgr.cpp 1671 2006-08-04 15:56:13Z luke $
00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE
00003 ================================XARAHEADERSTART===========================
00004  
00005                Xara LX, a vector drawing and manipulation program.
00006                     Copyright (C) 1993-2006 Xara Group Ltd.
00007        Copyright on certain contributions may be held in joint with their
00008               respective authors. See AUTHORS file for details.
00009 
00010 LICENSE TO USE AND MODIFY SOFTWARE
00011 ----------------------------------
00012 
00013 This file is part of Xara LX.
00014 
00015 Xara LX is free software; you can redistribute it and/or modify it
00016 under the terms of the GNU General Public License version 2 as published
00017 by the Free Software Foundation.
00018 
00019 Xara LX and its component source files are distributed in the hope
00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the
00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00022 See the GNU General Public License for more details.
00023 
00024 You should have received a copy of the GNU General Public License along
00025 with Xara LX (see the file GPL in the root directory of the
00026 distribution); if not, write to the Free Software Foundation, Inc., 51
00027 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
00028 
00029 
00030 ADDITIONAL RIGHTS
00031 -----------------
00032 
00033 Conditional upon your continuing compliance with the GNU General Public
00034 License described above, Xara Group Ltd grants to you certain additional
00035 rights. 
00036 
00037 The additional rights are to use, modify, and distribute the software
00038 together with the wxWidgets library, the wxXtra library, and the "CDraw"
00039 library and any other such library that any version of Xara LX relased
00040 by Xara Group Ltd requires in order to compile and execute, including
00041 the static linking of that library to XaraLX. In the case of the
00042 "CDraw" library, you may satisfy obligation under the GNU General Public
00043 License to provide source code by providing a binary copy of the library
00044 concerned and a copy of the license accompanying it.
00045 
00046 Nothing in this section restricts any of the rights you have under
00047 the GNU General Public License.
00048 
00049 
00050 SCOPE OF LICENSE
00051 ----------------
00052 
00053 This license applies to this program (XaraLX) and its constituent source
00054 files only, and does not necessarily apply to other Xara products which may
00055 in part share the same code base, and are subject to their own licensing
00056 terms.
00057 
00058 This license does not apply to files in the wxXtra directory, which
00059 are built into a separate library, and are subject to the wxWindows
00060 license contained within that directory in the file "WXXTRA-LICENSE".
00061 
00062 This license does not apply to the binary libraries (if any) within
00063 the "libs" directory, which are subject to a separate license contained
00064 within that directory in the file "LIBS-LICENSE".
00065 
00066 
00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS
00068 ----------------------------------------------
00069 
00070 Subject to the terms of the GNU Public License (see above), you are
00071 free to do whatever you like with your modifications. However, you may
00072 (at your option) wish contribute them to Xara's source tree. You can
00073 find details of how to do this at:
00074   http://www.xaraxtreme.org/developers/
00075 
00076 Prior to contributing your modifications, you will need to complete our
00077 contributor agreement. This can be found at:
00078   http://www.xaraxtreme.org/developers/contribute/
00079 
00080 Please note that Xara will not accept modifications which modify any of
00081 the text between the start and end of this header (marked
00082 XARAHEADERSTART and XARAHEADEREND).
00083 
00084 
00085 MARKS
00086 -----
00087 
00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara
00089 designs are registered or unregistered trademarks, design-marks, and/or
00090 service marks of Xara Group Ltd. All rights in these marks are reserved.
00091 
00092 
00093       Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK.
00094                         http://www.xara.com/
00095 
00096 =================================XARAHEADEREND============================
00097  */
00098 
00099 // dragmgr.cpp - Implementation of global dragging system manager (DragManagerOp)
00100 
00101 /*
00102 */
00103 
00104 
00105 #include "camtypes.h"
00106 
00107 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00108 #include "camelot.h"
00109 //#include "dialogop.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00110 #include "dragmgr.h"
00111 #include "keypress.h"
00112 //#include "oilcoord.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00113 #include "camframe.h"
00114 //#include "cursor.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00115 #include "csrstack.h"
00116 #include "gbrush.h"
00117 #include "grndrgn.h"
00118 
00119 #include "oilbitmap.h"
00120 #include "osrndrgn.h"
00121 
00122 CC_IMPLEMENT_DYNCREATE(DragManagerOp, Operation)
00123 IMPLEMENT_DYNAMIC_CLASS(CaptureHandler, wxEvtHandler)
00124 
00125 #define new CAM_DEBUG_NEW
00126 
00127 //------------------------------------------------------------------------------------------
00128 //      CaptureHandler
00129 //------------------------------------------------------------------------------------------
00130 
00131 // -----------------------------------------------------------------------------------------
00132 // CaptureHandler event table
00133 
00134 BEGIN_EVENT_TABLE( CaptureHandler, wxEvtHandler )
00135     EVT_LEFT_UP(            CaptureHandler::OnLButtonUp )
00136     EVT_RIGHT_UP(           CaptureHandler::OnRButtonUp )
00137     EVT_MOTION(             CaptureHandler::OnMouseMove )
00138 END_EVENT_TABLE()
00139 
00140 
00141 /********************************************************************************************
00142 
00143 >   CaptureHandler::CaptureHandler()
00144 
00145     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
00146     Created:    9/1/95
00147 
00148     Purpose:    CaptureHandler constructor 
00149 
00150 ********************************************************************************************/
00151 
00152 CaptureHandler::CaptureHandler(wxWindow* pWindow)
00153 {
00154 //  TRACEUSER("Gerry", _T("CaptureHandler::CaptureHandler"));
00155     m_pWindow = pWindow;
00156     m_bHasCapture = FALSE;
00157     m_pDisplayDC = NULL;
00158     m_pBackBitmap = NULL;
00159     m_pMaskBitmap = NULL;
00160 }
00161 
00162 /********************************************************************************************
00163 
00164 >   CaptureHandler::~CaptureHandler()
00165 
00166     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
00167     Created:    9/1/95
00168 
00169     Purpose:    CaptureWnd destructor 
00170 
00171 ********************************************************************************************/
00172 
00173 CaptureHandler::~CaptureHandler()
00174 {
00175 //  TRACEUSER("Gerry", _T("CaptureHandler::~CaptureHandler"));
00176     // Need to clean up all the pointers here...
00177 
00178     if (m_bHasCapture)
00179     {
00180         if (m_pWindow->PopEventHandler() != this)
00181         {
00182             TRACEUSER("Gerry", _T("Popped event handler is not this one, expect a crash"));
00183         }
00184 
00185         if (m_pWindow->HasCapture())
00186         {
00187             m_pWindow->ReleaseMouse();
00188             if (m_pWindow->HasCapture())
00189             {
00190                 TRACEUSER("Gerry", _T("Still got capture"));
00191             }
00192             else
00193             {
00194                 TRACEUSER("Gerry", _T("Capture released"));
00195             }
00196 
00197             CursorStack::GSetActive();
00198         }
00199         else
00200         {
00201             TRACEUSER("Gerry", _T("Haven't got capture"));
00202         }
00203         m_bHasCapture = FALSE;
00204     }
00205 }
00206 
00207 
00208 /********************************************************************************************
00209 
00210 >   BOOL CaptureHandler::StartCapture()
00211 
00212     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
00213     Created:    18/05/2006
00214 
00215     Purpose:    Attaches us to the window and starts mouse capture
00216 
00217 ********************************************************************************************/
00218 
00219 BOOL CaptureHandler::StartCapture()
00220 {
00221     TRACEUSER("Gerry", _T("CaptureHandler::StartCapture"));
00222     if (m_pWindow && !m_bHasCapture)
00223     {
00224         if (m_pWindow->HasCapture())
00225         {
00226             TRACEUSER("Gerry", _T("Already got capture"));
00227         }
00228 
00229         m_pWindow->CaptureMouse();
00230 
00231         if (m_pWindow->HasCapture())
00232         {
00233             TRACEUSER("Gerry", _T("Got capture"));
00234             m_bHasCapture = true;
00235             m_pWindow->PushEventHandler(this);
00236         }
00237     }
00238 
00239     return(TRUE);
00240 }
00241 
00242 
00243 //-------------------------------------------------------------------------------------------
00244 // CaptureHandler Message Handlers
00245 //-------------------------------------------------------------------------------------------
00246 
00247 /********************************************************************************************
00248 
00249 >   void CaptureHandler::OnLButtonUp(wxMouseEvent& event)
00250 
00251     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
00252     Created:    12/01/95
00253     Inputs:     MFC
00254     Purpose:    
00255     Errors:     -
00256     SeeAlso:    -
00257 
00258 ********************************************************************************************/
00259 void CaptureHandler::OnLButtonUp(wxMouseEvent& event)
00260 {
00261     if (m_pWindow)
00262     {
00263         wxPoint point = event.GetPosition();
00264         point = m_pWindow->ClientToScreen(point);
00265 
00266         if (DragManagerOp::CurrentManager && DragManagerOp::CurrentManager->CurrentDragInfo)
00267         {
00268             DragManagerOp::CurrentManager->CurrentDragInfo->OnMouseMove(point);
00269             DragManagerOp::CurrentManager->CurrentDragInfo->OnButtonUp(point);
00270         }
00271     }
00272 
00273     TRACEUSER("Gerry", _T("CaptureHandler::OnLButtonUp"));
00274     DragManagerOp::EndDrag(1);// 1 == left click for now
00275     // Don't call Skip as the window wont be expecting the button up
00276 //  event.Skip();
00277 }
00278 
00279 
00280 /********************************************************************************************
00281 
00282 >   void CaptureHandler::OnRButtonUp(wxMouseEvent& event)
00283 
00284     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
00285     Created:    12/01/95
00286     Inputs:     MFC
00287     Purpose:    
00288     Errors:     -
00289     SeeAlso:    -
00290 
00291 ********************************************************************************************/
00292 void CaptureHandler::OnRButtonUp(wxMouseEvent& event)
00293 {
00294     if (m_pWindow)
00295     {
00296         wxPoint point = event.GetPosition();
00297         point = m_pWindow->ClientToScreen(point);
00298 
00299         if (DragManagerOp::CurrentManager && DragManagerOp::CurrentManager->CurrentDragInfo)
00300         {
00301             DragManagerOp::CurrentManager->CurrentDragInfo->OnMouseMove(point);
00302             DragManagerOp::CurrentManager->CurrentDragInfo->OnButtonUp(point);
00303         }
00304     }
00305 
00306     TRACEUSER("Gerry", _T("CaptureHandler::OnRButtonUp"));
00307     DragManagerOp::EndDrag(-1);//   -1 == Right click for now
00308 
00309     // Don't call Skip as the window wont be expecting the button up
00310 //  event.Skip();
00311 }
00312 
00313 
00314 /********************************************************************************************
00315 
00316 >   void CaptureHandler::SetUpSolidDrag(CPoint StartPos)
00317 
00318     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
00319     Created:    12/01/95
00320     Inputs:     -
00321     Purpose:    Sets up Device Contexts / Bitmaps etc.. for Solid Drag
00322     Errors:     -
00323     SeeAlso:    -
00324 
00325 // ********************************************************************************************/
00326 
00327 BOOL CaptureHandler::SetUpSolidDrag(wxPoint StartPos)
00328 {
00329     TRACEUSER("Gerry", _T("SetUpSolidDrag(%d, %d)"), StartPos.x, StartPos.y);
00330 
00331     ERROR2IF(DragManagerOp::CurrentManager == NULL ||
00332              DragManagerOp::CurrentManager->CurrentDragInfo == NULL,
00333              FALSE,
00334              _T("CaptureHandler::SetUpSolidDrag - The current drag manager is invalid"));
00335 
00336     if (!DragManagerOp::CurrentManager->CurrentDragInfo->DoesSolidDrag)
00337         return TRUE;
00338 
00339     if (DragManagerOp::CurrentManager->RedrawInProgress || m_pDisplayDC != NULL)
00340         return FALSE;
00341 
00342     // get a couple of draggy bits
00343     wxPoint SolidDragOffset = DragManagerOp::CurrentManager->CurrentDragInfo->SolidDragOffset;
00344     wxSize DSize = DragManagerOp::CurrentManager->CurrentDragInfo->SolidDragSize;
00345 
00346     m_pDisplayDC = new wxScreenDC();
00347     wxMemoryDC BackGroundDC;
00348     m_pBackBitmap = new wxBitmap(DSize.x, DSize.y);
00349     
00350     if (m_pDisplayDC==NULL || m_pBackBitmap == NULL)
00351     {
00352         return FALSE;
00353     }
00354 
00355     // Offset the drag from the pointer
00356     wxPoint ClientPos = StartPos + SolidDragOffset;
00357 
00358     // select bitmap into the dc
00359     BackGroundDC.SelectObject(*m_pBackBitmap);
00360 
00361     ClientPos = m_pWindow->ScreenToClient(ClientPos);
00362 
00363     // init drag rect
00364     m_DragRect = wxRect(ClientPos.x, ClientPos.y, DSize.x, DSize.y);
00365 
00366     // blit the screen into the bitmap
00367     BackGroundDC.Blit(0,0,DSize.x,DSize.y,m_pDisplayDC,m_DragRect.x,m_DragRect.y);
00368 
00369     BackGroundDC.SelectObject(wxNullBitmap);
00370 
00371     INT32 DragTransparency = 
00372         DragManagerOp::CurrentManager->CurrentDragInfo->GetDragTransparency();
00373 
00374     KernelBitmap* DragMask = 
00375         DragManagerOp::CurrentManager->CurrentDragInfo->GetSolidDragMask();
00376     
00377     BOOL TransparentMask = DragManagerOp::CurrentManager->CurrentDragInfo->HasTransparentMask();
00378 
00379     if (DragTransparency > 0 || TransparentMask ||  DragMask != NULL)
00380     {
00381         // If we're doing a transparency drag, then we'll need
00382         // a monochome mask bitmap.
00383         // This will be a simple grey level, hatch pattern,
00384         // which will be used to 'knock' pixels out of the
00385         // drag bitmap.
00386 
00387         // Sadly, the world has conspired against us in terms of producing this
00388         // in any rational manner. 1bpp wxBitmaps do not work as brushes (random
00389         // memory). 24bpp wxBitmaps do not work as brushes into wxMemoryDCs backed
00390         // by 1bpp brushes. Conversion of 24bpp bitmaps to 1bpp does not dither.
00391         // making 1bpp brushes with a stipple does not dither. So we just manually
00392         // implement they bayer dithering algorithm.
00393 
00394         // Create a wxImage, don't initalize it
00395         wxImage MaskImage(DSize.x, DSize.y, false);
00396         unsigned char * pix=MaskImage.GetData();
00397         unsigned char * tpix = NULL;
00398 
00399         wxImage * pTransparentMask = NULL;
00400         if (TransparentMask)
00401         {
00402             wxBitmap *pTMbitmap=DragManagerOp::CurrentManager->CurrentDragInfo->GetTransparentMask();
00403             if (pTMbitmap)
00404                 pTransparentMask = new wxImage();
00405             if (!pTransparentMask)
00406                 TransparentMask=FALSE;
00407             else
00408             {
00409                 *pTransparentMask=pTMbitmap->ConvertToImage();
00410                 tpix=pTransparentMask->GetData();
00411             }
00412         }
00413 
00414         // DragTransparency is between 0 and 100,
00415         // and we need a grey level between 0 and 255.
00416         INT32 GreyLevel = (DragTransparency * 255) / 100;
00417 
00418         // for (i=0; i<4*4*3; i++) ImageData[i]=GreyLevel;
00419         // The above would be far too easy. wxWidgets doesn't seem to want to dither. Sigh
00420         // write our own ordered dither! And neither do 1bpp wxBitmaps work as brushes
00421         // sigh... And painting a 24bpp brush into a 1bpp bitmap dies horribly. Aaarrggghh
00422         // Bayer table
00423         INT32 OrderedDither[4*4]={ 1, 9, 3,11,
00424                                   13, 5,15, 7,
00425                                    4,12, 2,10,
00426                                   16, 8,14, 6};
00427         INT32 x, y;
00428 
00429         for (y=0; y<DSize.y; y++) for (x=0; x<DSize.x; x++)
00430         {
00431             INT32 tlevel=GreyLevel;
00432             if (TransparentMask)
00433             {
00434                 // Combine the transparency level with the transparency of the mask
00435                 // Note if EITHER are 255 we want full transparency. The appropriate
00436                 // operation is thus 1-((1-x)(1-y)), except of course they are 0..255
00437                 tlevel=((255*255+(255/2)) - // that's the maximum value (as we invert), but also add 255/2 for rounding when we divide by 255
00438                         ((255-GreyLevel)*(*tpix))
00439                         )/255;
00440                 tpix +=3;
00441             }
00442             BYTE thresh = (tlevel>(OrderedDither[(x&3)|((y&3)<<2)]*16-8))?0xff:0x00;
00443             // write three bytes (R, G, B)
00444             *pix++=thresh;
00445             *pix++=thresh;
00446             *pix++=thresh;
00447         }
00448 
00449         if (pTransparentMask)
00450             delete pTransparentMask;
00451 
00452         m_pMaskBitmap = new wxBitmap(MaskImage, 1);
00453         if (m_pMaskBitmap)
00454         {
00455             // Now combine the DragMask with the transparency mask.
00456             if (DragMask)
00457             {
00458                 wxMemoryDC MaskDC;
00459                 MaskDC.SelectObject(*m_pMaskBitmap);
00460 
00461                 // This needs to create a wxBitmap from DragMask
00462                 // and OR it into the MaskDC
00463 
00464                 CWxBitmap* pMaskBmp = (CWxBitmap*)DragMask->ActualBitmap;
00465                 RGBQUAD* Palette = (RGBQUAD *) (pMaskBmp->BMInfo->bmiColors);
00466 
00467                 // set the first colours to black and white
00468                 Palette[0].rgbRed = Palette[0].rgbBlue = Palette[0].rgbGreen = 0;
00469                 Palette[1].rgbRed = Palette[1].rgbBlue = Palette[1].rgbGreen = 255;
00470 
00471                 // set the reserved bytes to zero
00472                 Palette[0].rgbReserved = Palette[1].rgbReserved = 0;
00473 
00474                 UINT32 bpp=pMaskBmp->GetBPP();
00475 
00476                 wxMemoryDC MemDC;
00477                 wxBitmap MemBitmap(DSize.x, DSize.y, bpp);
00478                 MemDC.SelectObject(MemBitmap);
00479 
00480                 if (bpp>8)
00481                     bpp=32;
00482 
00483                 LPBYTE MemBBits;
00484                 LPBITMAPINFO MemBInfo = AllocDIB(DSize.x, DSize.y, bpp, &MemBBits);
00485 
00486                 GRenderRegion::StaticPlotBitmap(&MemDC, DIB_RGB_COLORS, MemBInfo, MemBBits, 0, 0, DSize.x, DSize.y, m_pMaskBitmap->GetPalette(), 0, 0);
00487     
00488                 // Now OR the Mask Bitmap into the MaskDC, so that
00489                 // it 'masks' the transparency mask.
00490                 MaskDC.Blit(0, 0, DSize.x, DSize.y, &MemDC, 0, 0, wxOR);
00491     
00492                 // clean up the dc
00493                 MaskDC.SetBrush(*wxTRANSPARENT_BRUSH);
00494                 MaskDC.SetPen(*wxTRANSPARENT_PEN);
00495                 MaskDC.SelectObject(wxNullBitmap);
00496             }
00497         }
00498     }
00499     else
00500         m_pMaskBitmap = NULL;
00501 
00502     DrawSolidDrag(StartPos);
00503 
00504     return TRUE;
00505 }
00506 
00507 
00508 
00509 /********************************************************************************************
00510 
00511 >   BOOL CaptureHandler::CleanUpSolidDrag()
00512 
00513     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
00514     Created:    12/01/95
00515     Inputs:     -
00516 
00517     Returns:    FALSE if it fails
00518 
00519     Purpose:    Removes any solid-drag stuff we may have on-screen at the moment and cleans up
00520                 the solid drag system. Called at the end of a drag to clean up, and also
00521                 whenever someone is redrawing underneath us, and we thus need to remove the 
00522                 drag stuff while they redraw.
00523     Errors:     -
00524     SeeAlso:    CaptureHandler::CleanUpSolidDragInScreenArea
00525 
00526 ********************************************************************************************/
00527 
00528 BOOL CaptureHandler::CleanUpSolidDrag()
00529 {
00530     TRACEUSER("Gerry", _T("CleanUpSolidDrag"));
00531 
00532     if (DragManagerOp::CurrentManager == NULL)
00533         return(FALSE);
00534 
00535     if (DragManagerOp::CurrentManager->CurrentDragInfo &&
00536         !DragManagerOp::CurrentManager->CurrentDragInfo->DoesSolidDrag)
00537        return TRUE;
00538 
00539     if (m_pDisplayDC == NULL)
00540         return FALSE;
00541 
00542     if (m_pBackBitmap)
00543     {
00544         wxMemoryDC BackGroundDC;
00545     
00546         // select bitmap into the dc
00547         BackGroundDC.SelectObject(*m_pBackBitmap);
00548 
00549         // remove the last drag draw (only if we drew something)
00550         if (!DragManagerOp::CurrentManager->DragPending)
00551         {
00552             m_pDisplayDC->Blit(m_DragRect.x,m_DragRect.y,m_DragRect.width, m_DragRect.height,&BackGroundDC,0,0);
00553         }
00554 
00555         // clean up  and delete the DC's
00556         BackGroundDC.SelectObject(wxNullBitmap);
00557     }
00558 
00559     if (m_pDisplayDC)
00560     {
00561         delete m_pDisplayDC;
00562         m_pDisplayDC = NULL;
00563     }
00564 
00565     if (m_pBackBitmap)
00566     {
00567         delete m_pBackBitmap;
00568         m_pBackBitmap = NULL;
00569     }
00570 
00571     if (m_pMaskBitmap)
00572     {
00573         delete m_pMaskBitmap;
00574         m_pMaskBitmap = NULL;
00575     }
00576 
00577     m_DragRect = wxRect(0, 0, 0, 0);
00578 
00579     return TRUE;
00580 }
00581 
00582 
00583 
00584 /********************************************************************************************
00585 
00586 >   BOOL CaptureHandler::CleanUpSolidDragInScreenArea(const wxRect& Area)
00587 
00588     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00589     Created:    8/5/95
00590 
00591     Inputs:     Area - The SCREEN coordinates of the area ofd screen which has become
00592                 compromised (usually because it is being redrawn).
00593 
00594     Returns:    TRUE if it called CleanUpSolidDrag, FALSE if it didn't bother
00595 
00596     Purpose:    Calls CleanUpSolidDrag. However, it ONLY calls that method if the
00597                 compromised screen area overlaps the solid drag area - if not, then the
00598                 solid drag stuff can't be overwritten, so there is no need to remove it.
00599                 This can drastically reduce flicker when things are background redrawing
00600                 on other parts of the screen.
00601 
00602     SeeAlso:    CaptureHandler::CleanUpSolidDrag
00603 
00604 ********************************************************************************************/
00605 
00606 BOOL CaptureHandler::CleanUpSolidDragInScreenArea(const wxRect& Area)
00607 {
00608 //  TRACEUSER("Gerry", _T("CleanUpSolidDragInScreenArea"));
00609 
00610     // No solid drag, so no need to do anything
00611     if (!DragManagerOp::CurrentManager->CurrentDragInfo->DoesSolidDrag)
00612        return(FALSE);
00613 
00614     // No solid stuff has yet been drawn, so no need to do anything
00615     if (DragManagerOp::CurrentManager->DragPending || m_DragRect.IsEmpty())
00616         return(FALSE);
00617 
00618     wxRect Isect(Area);
00619     if (!Isect.Intersect(m_DragRect).IsEmpty())
00620     {
00621         CleanUpSolidDrag();
00622         return(TRUE);
00623     }
00624 
00625     return(FALSE);
00626 }
00627 
00628 
00629 
00630 /********************************************************************************************
00631 
00632 >   void CaptureHandler::OnMouseMove(wxMouseEvent& event)
00633 
00634     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
00635     Created:    12/01/95
00636     Inputs:     MFC
00637     Purpose:    call solid drag draw code.
00638     Errors:     -
00639     SeeAlso:    -
00640 
00641 ********************************************************************************************/
00642 
00643 void CaptureHandler::OnMouseMove(wxMouseEvent& event)
00644 {
00645 //  TRACEUSER("Gerry", _T("CaptureHandler::OnMouseMove"));
00646     // Abort if the system has been disabled (for an error box)
00647     if (CCamApp::IsDisabled())
00648     {
00649 //      DragManagerOp::AbortDrag();     // This could be deeply scary - it mustn't cause a redraw!
00650         return;
00651     }
00652 
00653     if (DragManagerOp::CurrentManager && !DragManagerOp::CurrentManager->RedrawInProgress)
00654     {
00655         wxPoint point = event.GetPosition();
00656         point = m_pWindow->ClientToScreen(point);
00657 
00658         if (DragManagerOp::CurrentManager->CurrentDragInfo)
00659             DragManagerOp::CurrentManager->CurrentDragInfo->OnMouseMove(point);
00660 
00661         DrawSolidDrag(point);
00662     }
00663 }
00664 
00665 
00666 
00667 /********************************************************************************************
00668 
00669 >   void CaptureHandler::DrawSolidDrag(wxPoint point)
00670 
00671     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
00672     Created:    12/01/95
00673     Inputs:     Screen Coord
00674     Purpose:    to allow solid flicker-free drag objects to be drawn.
00675                 a helper function in the current drag is called - but this function
00676                 looks after the rest.
00677     Errors:     -
00678     SeeAlso:    -
00679 
00680 ********************************************************************************************/
00681 
00682 BOOL CaptureHandler::DrawSolidDrag(wxPoint point)
00683 {
00684     // ignore if not intialized
00685     if (!m_pBackBitmap || !m_pDisplayDC)
00686         return FALSE;
00687 
00688 //  TRACEUSER("Gerry", _T("DrawSolidDrag(%d, %d)"), point.x, point.y);
00689 
00690     ERROR2IF(DragManagerOp::CurrentManager == NULL ||
00691              DragManagerOp::CurrentManager->CurrentDragInfo == NULL,
00692              FALSE,
00693              "No current drag in CaptureHandler::DrawSolidDrag!");
00694     
00695     // not interested ? ...
00696     if(DragManagerOp::CurrentManager->DragPending)
00697         return TRUE;
00698     if(!DragManagerOp::CurrentManager->CurrentDragInfo->DoesSolidDrag)
00699         return TRUE;
00700 
00701     INT32 DragTransparency = DragManagerOp::CurrentManager->CurrentDragInfo->
00702                                                             GetDragTransparency();
00703     // If the Drag Info says it wants to be transparent,
00704     // then call the transparent drag routine.
00705     if (DragTransparency > 0 || m_pMaskBitmap != NULL)
00706     {
00707         if (DrawTransparentDrag(point, DragTransparency))
00708             return TRUE;
00709 
00710         // If the Transparency Drag fails (eg. not enough resources under Win32s !!)
00711         // then just fall though, and try a normal solid drag .....
00712     }
00713 
00714     // offset mouse pos by drag offset
00715     point += DragManagerOp::CurrentManager->CurrentDragInfo->SolidDragOffset;
00716 
00717     // size of solid drag draw bounds
00718     wxSize DSize = DragManagerOp::CurrentManager->CurrentDragInfo->SolidDragSize;
00719 
00720     // create a few DCs !!!
00721     
00722     // this one will hold the old background
00723     wxMemoryDC BackDC;
00724     
00725     // select bitmap into the dc
00726     BackDC.SelectObject(*m_pBackBitmap);
00727 
00728     // this one is just temp
00729     wxMemoryDC ScratchDC;
00730     wxBitmap ScratchBit(DSize.x, DSize.y);
00731 
00732     // select bitmap into the dc
00733     ScratchDC.SelectObject(ScratchBit);
00734     
00735     // make copy of last rect
00736     wxRect OldRect(m_DragRect);
00737     
00738     // set new drag draw bounds
00739     m_DragRect = wxRect(point.x, point.y, DSize.x, DSize.y);
00740     
00741     // Copy screen to new background
00742     ScratchDC.Blit(0,0,DSize.x,DSize.y,m_pDisplayDC,m_DragRect.x,m_DragRect.y);
00743     
00744     wxPoint Change = OldRect.GetPosition() - m_DragRect.GetPosition();
00745     
00746     // Replace part of new bkg with old background
00747     if (!OldRect.IsEmpty())
00748         ScratchDC.Blit(Change.x,Change.y,DSize.x,DSize.y,&BackDC,0,0);
00749 
00750     // Copy image to screen
00751     DragManagerOp::CurrentManager->CurrentDragInfo->
00752         OnDrawSolidDrag(m_DragRect.GetPosition(), m_pDisplayDC);
00753 
00754     // Copy part of image to old background
00755     DragManagerOp::CurrentManager->CurrentDragInfo->
00756         OnDrawSolidDrag(wxPoint(-Change.x,-Change.y), &BackDC);
00757     
00758     // Copy old background to screen
00759     if (!OldRect.IsEmpty())
00760         m_pDisplayDC->Blit(OldRect.x,OldRect.y,DSize.x,DSize.y,&BackDC,0,0);
00761 
00762     // copy new background into old for next time round
00763     BackDC.Blit(0,0,DSize.x,DSize.y,&ScratchDC,0,0);
00764 
00765     // clean up and delete scratch dc and bitmap
00766     ScratchDC.SelectObject(wxNullBitmap);
00767 
00768     BackDC.SelectObject(wxNullBitmap);
00769 
00770     return TRUE;
00771 }
00772 
00773 
00774 /********************************************************************************************
00775 
00776 >   void CaptureHandler::DrawTransparentDrag(wxPoint point)
00777 
00778     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00779     Created:    19/03/95
00780     Inputs:     Screen Coord
00781     Purpose:    to allow solid flicker-free semi-transparent drag objects to be drawn.
00782                 a helper function in the current drag is called - but this function
00783                 looks after the rest.
00784     Errors:     -
00785     SeeAlso:    -
00786 
00787 ********************************************************************************************/
00788 
00789 BOOL CaptureHandler::DrawTransparentDrag(wxPoint point, INT32 Transparency)
00790 {
00791 //  TRACEUSER("Gerry", _T("DrawTransparentDrag(%d, %d, %d)"), point.x, point.y, Transparency);
00792 
00793     // offset mouse pos by drag offset
00794     point += DragManagerOp::CurrentManager->CurrentDragInfo->SolidDragOffset;
00795 
00796     // size of solid drag draw bounds
00797     wxSize DSize = DragManagerOp::CurrentManager->CurrentDragInfo->SolidDragSize;
00798 
00799     // create a few DCs !!!
00800     // this one will hold the old background
00801     wxMemoryDC BackDC;
00802 
00803     // select bitmap into the dc
00804     BackDC.SelectObject(*m_pBackBitmap);
00805 
00806     // this one is just temp
00807     wxMemoryDC ScratchDC;
00808     wxBitmap ScratchBit(DSize.x,DSize.y);
00809 
00810     wxBitmap TempBitmap(DSize.x, DSize.y);
00811     wxMemoryDC TempDC;
00812 
00813     wxMemoryDC MaskDC;
00814 
00815     // select bitmap into the dc
00816     ScratchDC.SelectObject(ScratchBit);
00817     
00818     // make copy of last rect
00819     wxRect OldRect = m_DragRect;
00820     
00821     // set new drag draw bounds
00822     m_DragRect = wxRect(point.x,point.y,DSize.x,DSize.y);
00823     
00824     // Copy screen to new background
00825     ScratchDC.Blit(0,0,DSize.x,DSize.y,m_pDisplayDC,m_DragRect.x,m_DragRect.y);
00826 
00827     wxPoint Change = OldRect.GetPosition() - m_DragRect.GetPosition();
00828 
00829     // Replace part of new bkg with old background
00830     if (!OldRect.IsEmpty())
00831         ScratchDC.Blit(Change.x,Change.y,DSize.x,DSize.y,&BackDC,0,0);
00832 
00833     TempDC.SelectObject(TempBitmap);
00834 
00835     // Render into the temporary bitmap
00836     DragManagerOp::CurrentManager->CurrentDragInfo->
00837         OnDrawSolidDrag(wxPoint(0,0), &TempDC);
00838 
00839     // set the colours for the masking
00840 //  TempDC.SetBkColor(RGB(0,0,0));
00841 //  TempDC.SetTextColor(RGB(255,255,255));
00842 
00843     MaskDC.SelectObject(*m_pMaskBitmap);
00844 
00845     TempDC.Blit(0, 0, DSize.x, DSize.y, &MaskDC, 0, 0, wxAND_INVERT);
00846 
00847     wxBitmap OffScreenBmp(DSize.x, DSize.y);
00848     wxMemoryDC OffScreenDC;
00849     OffScreenDC.SelectObject(OffScreenBmp);
00850 
00851     OffScreenDC.Blit(0, 0, DSize.x, DSize.y, &ScratchDC, 0, 0);
00852 
00853     OffScreenDC.Blit(0, 0, DSize.x, DSize.y, &MaskDC, 0, 0, wxAND);
00854 
00855     OffScreenDC.Blit(0, 0, DSize.x, DSize.y, &TempDC, 0, 0, wxOR);
00856 
00857     // Copy part of image to old background
00858     BackDC.Blit(-Change.x,-Change.y, DSize.x, DSize.y, &OffScreenDC, 0,0);
00859     
00860     // Copy image to screen
00861     m_pDisplayDC->Blit(m_DragRect.x, m_DragRect.y, DSize.x, DSize.y, &OffScreenDC, 0, 0);
00862 
00863     // Copy old background to screen
00864     if(!OldRect.IsEmpty())
00865         m_pDisplayDC->Blit(OldRect.x, OldRect.y, DSize.x, DSize.y, &BackDC, 0, 0);
00866     
00867     // copy new background into old for next time round
00868     BackDC.Blit(0, 0, DSize.x, DSize.y, &ScratchDC, 0, 0);
00869 
00870     // clean up and delete DCs and bitmaps
00871     OffScreenDC.SelectObject(wxNullBitmap);
00872     TempDC.SelectObject(wxNullBitmap);
00873     MaskDC.SelectObject(wxNullBitmap);
00874     ScratchDC.SelectObject(wxNullBitmap);
00875     BackDC.SelectObject(wxNullBitmap);
00876 
00877     return TRUE;
00878 }
00879 
00880 
00881 //------------------------------------------------------------------------------------------
00882 //              Drag ManagerOp
00883 //------------------------------------------------------------------------------------------
00884 
00885 // -----------------   STATICS
00886 
00887 DragManagerOp *DragManagerOp::CurrentManager = NULL;
00888 CaptureHandler  *DragManagerOp::TheCaptureHandler = NULL;
00889 
00890 // Drag delay and distance. These are not the suggested OLE-2 default values, because
00891 // those values are mindbogglingly dumb (2 pixels, which makes it dead easy to accidentally
00892 // start a drag if the mouse wobbles, and 0.2 secs which means any non-fast click
00893 // will always be a drag).
00894 const UINT32 DEFAULT_DRAGDIST    = 6;   // 6 pixel "radius" outside which click becomes drag
00895 const UINT32 DEFAULT_DRAGDELAY = 400;   // 400 millisecond (0.4 sec) delay before click=>drag
00896 UINT32 DragManagerOp::DragMinDist   = DEFAULT_DRAGDIST;
00897 UINT32 DragManagerOp::DragDelay = DEFAULT_DRAGDELAY;
00898 
00899 MonotonicTime DragManagerOp::DragStartTimer;
00900 BOOL DragManagerOp::DragPending = FALSE;
00901 BOOL DragManagerOp::DragEnded = FALSE;
00902 BOOL DragManagerOp::DragActive = FALSE;
00903 
00904 wxRect DragManagerOp::DragStartRect;
00905 wxRect DragManagerOp::StillClickRect;
00906 
00907 BOOL DragManagerOp::RedrawInProgress = FALSE;
00908 
00909 UINT32 DragManagerOp::StatusLineStringID = 0;
00910 
00911 DragInformation * DragManagerOp::CurrentDragInfo = NULL;    // Descriptor of current drag
00912 DragTarget * DragManagerOp::CurrentDragTarget = NULL;       // Current drag target
00913 
00914 
00915 
00916 /********************************************************************************************
00917 
00918 >   DragManagerOp::DragManagerOp()
00919 
00920     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00921     Created:    9/1/95
00922 
00923     Purpose:    DragManagerOp constructor - DO NOT CALL THE DEFAULT CONSTRUCTOR!
00924 
00925 ********************************************************************************************/
00926 
00927 DragManagerOp::DragManagerOp()
00928 {
00929     ERROR3("DragManagerOp::DragManagerOp - Illegal (default) constructor called!\n");
00930 
00931     ERROR3IF(CurrentManager != NULL, "Attempt to start a drag while already dragging!");
00932     CurrentManager = this;
00933 
00934     CurrentID = 0;
00935     CurrentCursor = NULL;
00936 }
00937 
00938 
00939 
00940 /********************************************************************************************
00941 
00942 >   DragManagerOp::DragManagerOp(DragInformation *Descriptor)
00943 
00944     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00945     Created:    9/1/95
00946 
00947     Inputs:     Descriptor - Describes the current drag. May not be NULL.
00948 
00949     Purpose:    DragManagerOp constructor
00950 
00951 ********************************************************************************************/
00952 
00953 DragManagerOp::DragManagerOp(DragInformation *Descriptor)
00954 {
00955     ERROR3IF(Descriptor == NULL, "DragManagerOp must be given a valid DragInformation ptr");
00956     ERROR3IF(CurrentManager != NULL, "Attempt to start a drag while already dragging!");
00957 
00958     AbortDrag();
00959     CurrentManager  = this;
00960     CurrentDragInfo = Descriptor;
00961 
00962     CurrentKeypress = NULL;
00963     
00964     DragEnded = FALSE;
00965 
00966     CurrentID = 0;
00967     CurrentCursor = NULL;
00968 
00969     // get system drag start values. We override the default values suggested by the
00970     // OLE2 docs, because their values are stupid. (2 pixels? Bleedin' heck! I wish MY
00971     // mouse was that steady!). However, we red the values from Win.INI like good boys, so
00972     // the user can override them if they so desire.
00973 //  DragMinDist = GetProfileInt("windows", "DragMinDist", DEFAULT_DRAGDIST);
00974 //  DragDelay = GetProfileInt("windows", "DragDelay", DEFAULT_DRAGDELAY);
00975 
00976     DragMinDist = DEFAULT_DRAGDIST;
00977     DragDelay = DEFAULT_DRAGDELAY;
00978 
00979     DragStartRect = wxRect();
00980 }
00981 
00982 
00983 
00984 /********************************************************************************************
00985 
00986 >   DragManagerOp::~DragManagerOp()
00987 
00988     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00989     Created:    9/1/95
00990 
00991     Purpose:    DragManagerOp destructor
00992 
00993 ********************************************************************************************/
00994 
00995 DragManagerOp::~DragManagerOp()
00996 {
00997     // Ensure all memory allocations are deleted
00998     CleanUpAfterDrag();
00999 
01000     // We are no longer the current drag manager
01001     CurrentManager = NULL;
01002 
01003     DragActive = FALSE;
01004 
01005     StatusLineStringID = 0; 
01006 
01007     if (CurrentCursor)
01008         delete CurrentCursor;
01009 }
01010 
01011 
01012 
01013 /********************************************************************************************
01014 
01015 >   static CPoint DragManagerOp::GetDragMousePos()
01016 
01017     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
01018     Created:    9/1/95
01019 
01020     Purpose:    return a CPoint for the Last Mouse Position
01021 
01022 ********************************************************************************************/
01023 
01024 wxPoint DragManagerOp::GetDragMousePos()
01025 {
01026     wxPoint MPos(0,0);
01027     
01028     if( CurrentManager != NULL )
01029         MPos = CurrentManager->CurrentMousePos;
01030     return MPos;
01031 }
01032 
01033 
01034 /********************************************************************************************
01035 
01036 >   static CaptureHandler * DragManagerOp::GetDragCaptureHandler()
01037 
01038     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
01039     Created:    9/1/95
01040 
01041     Purpose:    return the capture handler
01042 
01043 ********************************************************************************************/
01044 
01045 CaptureHandler *DragManagerOp::GetDragCaptureHandler()
01046 {
01047     if( CurrentManager == NULL )
01048         return NULL;
01049     
01050     return TheCaptureHandler;
01051 }
01052 
01053 /********************************************************************************************
01054 
01055 >   static CaptureWnd * DragManagerOp::GetCurrentDragInfo()
01056 
01057     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
01058     Created:    9/1/95
01059 
01060     Purpose:    return Current drag information
01061 
01062 ********************************************************************************************/
01063 
01064 DragInformation * DragManagerOp::GetCurrentDragInfo()
01065 {
01066     if( CurrentManager == NULL )
01067         return NULL;
01068     
01069     return CurrentDragInfo;
01070 
01071 }
01072 
01073 
01074 
01075 /********************************************************************************************
01076 
01077 >   static void DragManagerOp::StartDrag(DragInformation *Descriptor, CWindowID DragWindow)
01078 
01079     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01080     Created:    9/1/95
01081 
01082     Inputs:     Descriptor - A DragInformation object describing the current drag.
01083                 NOTE WELL that this is given to the DragManager, who is then responsible
01084                 for deleting it when the drag completes. DO NOT DELETE IT!
01085                 DragWindow - The window that is starting the drag.
01086                 NOTE: For correct operation under wxGTK this must be the window that
01087                 received the button down event that started this drag
01088 
01089     Purpose:    Starts a global-drag off
01090                 This will create a new DragManagerOp object, set up the drag, and
01091                 broadcast a DragMsg DRAGSTARTED, as a result of which, DragTargets
01092                 should be created by interested parties (these will register with the
01093                 Drag Manager, and then be called to handle events during the drag)
01094 
01095 ********************************************************************************************/
01096 
01097 void DragManagerOp::StartDrag(DragInformation *Descriptor, CWindowID DragWindow)
01098 {
01099     if (Descriptor == NULL)
01100     {
01101         // Handle a NULL pointer by just not starting up the drag
01102         TRACE( _T("NULL Descriptor given to DragManagerOp::StartDrag()\n"));
01103         return;
01104     }
01105 
01106     ERROR3IF(Descriptor == NULL, "DragManagerOp must be given a valid DragInformation ptr");
01107 
01108     DragManagerOp* pNewManager = new DragManagerOp(Descriptor);
01109 
01110     if (Descriptor->IsAdjustDrag)       // Adjust drags just immediately become clicks
01111     {
01112         DragPending = TRUE;             // Make sure it turns into a click properly (see EndDrag)
01113         if (pNewManager != NULL)
01114         {
01115             pNewManager->CurrentMousePos = wxGetMousePosition();
01116             pNewManager->InitialMousePos = pNewManager->LastMousePos = pNewManager->CurrentMousePos;
01117 
01118             EndDrag(-1);
01119         }
01120         return;
01121     }
01122 
01123     if (pNewManager != NULL)
01124     {
01125         // Attach the CaptureHandler to the correct window
01126         wxWindow* pWindow = (wxWindow*)DragWindow;
01127         if (pWindow == NULL)
01128             pWindow = GetMainFrame();
01129 
01130         TheCaptureHandler = new CaptureHandler(pWindow);
01131         if (TheCaptureHandler != NULL)
01132         {
01133             DragPending = TRUE;
01134             
01135             // Remember where the mouse is at the start of the drag
01136             pNewManager->CurrentMousePos = wxGetMousePosition();
01137             pNewManager->InitialMousePos = pNewManager->LastMousePos = pNewManager->CurrentMousePos;
01138 
01139             // Request that all interested parties attach DragTargets now
01140             BROADCAST_TO_ALL(DragMessage(DragMessage::DRAGSTARTED, pNewManager, Descriptor));
01141 
01142             // views don't receive messages so we'll have to do this the hard way..
01143             // App->Document->View... 
01144             GetApplication()->CreateDragTargets(Descriptor);
01145 
01146             // Send an Initialise event to all registered targets
01147 
01148             // Forget this - drags with no targets are perfectly legal - see colour picker
01149 #if 0
01150 #ifdef _DEBUG
01151             if (pNewManager->Targets.IsEmpty())
01152                 TRACE( _T("DragManagerOp::StartDrag - No drag targets specified for this drag!"));
01153 #endif
01154 #endif
01155             pNewManager->ProcessEvent(DRAGEVENT_INITIALISE);        
01156 
01157             // Start the mouse capture
01158             TheCaptureHandler->StartCapture();
01159 
01160             // Register for idle events
01161             GetApplication()->RegisterIdleProcessor(IDLEPRIORITY_HIGH, pNewManager);
01162 
01163             // get drag start time
01164             DragStartTimer.Sample();
01165 
01166             // we will use this rect to test whether we have started a drag
01167             StillClickRect = wxRect( pNewManager->InitialMousePos.x - DragMinDist,
01168                                     pNewManager->InitialMousePos.y - DragMinDist,
01169                                     DragMinDist * 2,
01170                                     DragMinDist * 2);
01171             SetDragActive(TRUE);
01172         }
01173     }
01174     GetMainFrame()->SetFocus();
01175 }
01176 
01177 
01178 
01179 /********************************************************************************************
01180 
01181 >   static void DragManagerOp::EndDrag(INT32 Flags)
01182 
01183     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
01184     Created:    9/1/95
01185     Purpose:
01186     Input  :  Flags : mouse button state( 1=leftclick/-1= rightclick )  
01187 
01188 ********************************************************************************************/
01189 
01190 void DragManagerOp::EndDrag(INT32 Flags)
01191 {
01192     if(!CurrentManager)
01193         return;
01194 
01195     // clean up
01196     if (TheCaptureHandler != NULL)
01197     {
01198         TheCaptureHandler->CleanUpSolidDrag();
01199     }
01200 
01201     if(DragPending)      // not a drag - user intended a click
01202     {
01203         // call the click handler in the drag
01204         wxPoint StartMouse;
01205         StartMouse.x = CurrentManager->InitialMousePos.x;
01206         StartMouse.y = CurrentManager->InitialMousePos.y;
01207         CurrentManager->CurrentDragInfo->OnClick(Flags,StartMouse);
01208     }
01209     else                // this is a genuine end of drag
01210     {
01211         // Update the mouse position, so we give the event to the correct target
01212         CurrentManager->LastMousePos = CurrentManager->CurrentMousePos;
01213         CurrentManager->CurrentMousePos = wxGetMousePosition();
01214 
01215         // Process the drag completion event
01216         DragEventType Event = DRAGEVENT_COMPLETED;
01217         CurrentManager->ProcessEvent(Event);
01218 
01219         // make sure we don't get any idles after the drag has finished
01220         DragEnded = TRUE;
01221     }
01222 
01223     // Let all drag targets know that the drag is well and truly dead
01224     if (CurrentManager)
01225         CurrentManager->ProcessEvent(DRAGEVENT_DEINITIALISE);
01226 
01227     SetDragActive(FALSE);
01228 
01229     // end this op
01230     if (CurrentManager)
01231         CurrentManager->End();
01232 }
01233 
01234 
01235 /********************************************************************************************
01236 
01237 >   static void DragManagerOp::AbortDrag(void)
01238 
01239     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01240     Created:    9/1/95
01241 
01242     Purpose:    To forcibly abort the current drag. If there is no current drag, then
01243                 nothing happens (so it can be called just to ensure that no drag is
01244                 left current on exit for example)
01245 
01246 ********************************************************************************************/
01247 
01248 void DragManagerOp::AbortDrag(void)
01249 {
01250     if (CurrentManager != NULL)
01251     {
01252         CurrentManager->LastMousePos = CurrentManager->CurrentMousePos;
01253         CurrentManager->CurrentMousePos = wxGetMousePosition();
01254 
01255         if (TheCaptureHandler != NULL)
01256             TheCaptureHandler->CleanUpSolidDrag();
01257 
01258         CurrentManager->ProcessEvent(DRAGEVENT_ABORT);
01259 
01260         // Let all drag targets know that the drag is well and truly dead
01261         CurrentManager->ProcessEvent(DRAGEVENT_DEINITIALISE);
01262 
01263         CurrentManager->End();
01264     }
01265 
01266     SetDragActive(FALSE);   
01267 }
01268 
01269 
01270 
01271 /********************************************************************************************
01272 
01273 >   static DragManagerOp *DragManagerOp::GetCurrentManager(void)
01274 
01275     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01276     Created:    9/1/95
01277 
01278     Returns:    NULL (if no current drag), or a pointer to the current DragManagerOp
01279 
01280     Purpose:    To find the current drag manager
01281 
01282 ********************************************************************************************/
01283 
01284 DragManagerOp *DragManagerOp::GetCurrentManager(void)
01285 {
01286     return(CurrentManager);
01287 }
01288 
01289 
01290 
01291 /********************************************************************************************
01292 
01293 >   virtual BOOL DragManagerOp::ProcessEvent(DragEventType Event)
01294 
01295     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01296     Created:    9/1/95
01297 
01298     Inputs:     Event - Indicates what type of Drag Event is occurring
01299 
01300     Returns:    TRUE if a DragTarget claimed the event
01301 
01302     Purpose:    To process global drag events 
01303                 This method calls each DragTarget event processor in turn (until one
01304                 claims the event), with the event. The 3 'Current' member variables are
01305                 passed in to the event processor, so ensure they are set up appropriately
01306                 before calling this method.
01307 
01308     Notes:      DragTargets can safely de-register themselves during processing of the
01309                 events (i.e. the list traversal code won't get upset)
01310 
01311                 When calling a kernel target which includes both a dialogue ID and a gadget,
01312                 the coordinates passed into the event handler are millipoint offsets from
01313                 the bottom left corner of the gadget, just as with n