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 normal kernel-rendered
01314                 gadgets. Note that the event will not be passed to the gadget unless the
01315                 mouse pointer is over the gadget window. If no gadget is specified, then
01316                 the mouse coordinates will always be (0,0) at present.
01317 
01318                 The INITIALISE and DEINITIALISE events are broadcast to all active targets,
01319                 while all other events are broadcast only to general (no target window)
01320                 targets, and the target (if any) over which the mouse pointer lies.
01321 
01322     SeeAlso:    keyword DragEventType
01323     SeeAlso:    DragTarget::ProcessEvent
01324 
01325 ********************************************************************************************/
01326 
01327 BOOL DragManagerOp::ProcessEvent(DragEventType Event)
01328 {
01329     BOOL BroadcastToAll = FALSE;        // Determine if the event goes to everybody or
01330                                     // only to target under the pointer
01331     if (Event == DRAGEVENT_INITIALISE || Event == DRAGEVENT_DEINITIALISE)
01332         BroadcastToAll = TRUE;
01333 
01334     if(CurrentManager == NULL || (DragEnded && Event != DRAGEVENT_DEINITIALISE))
01335         return FALSE;
01336 
01337     LastEvent = Event;          // Remember the type of the last event we processed
01338     
01339     DragTarget *Ptr  = (DragTarget *) Targets.GetHead();
01340     DragTarget *Next;
01341 
01342     OilCoord KernelMousePos(0,0);
01343     wxPoint   WinoilMousePos(CurrentMousePos);
01344     CurrentDragTarget = NULL;
01345     BOOL OverTarget = FALSE;
01346 
01347 //  TRACEUSER("Gerry", _T("ProcessEvent = (%d, %d)"), WinoilMousePos.x, WinoilMousePos.y);
01348 
01349     while (Ptr != NULL)
01350     {
01351         // Copy the mouse position, as each iteration of the loop corrupts it
01352         WinoilMousePos = CurrentMousePos;
01353 
01354         // Allow things like targets de-registering during processing
01355         Next = (DragTarget *) Targets.GetNext(Ptr);
01356         BOOL GoAhead = TRUE;
01357         
01358         if (Ptr->IsAKernelObject())
01359         {
01360             KernelMousePos = OilCoord(0,0);
01361 
01362             DialogOp  *pDialogOp;
01363             CGadgetID GadgetID;
01364             Ptr->GetTargetAreaInfo(&pDialogOp, &GadgetID);
01365 
01366             if (pDialogOp != NULL)
01367             {
01368                 wxWindow* TargetWindow = (wxWindow*)pDialogOp->WindowID;    // use whole window if no gadget specified
01369 
01370                 if (GadgetID != 0)
01371                     TargetWindow = TargetWindow->FindWindow((INT32)GadgetID);
01372 
01373                 // We want to do the following. But it doesn't work because GetRect() is relative to the
01374                 // parent window when TargetWindow is not a TLW. What we need is (consistently) screen
01375                 // coordinates
01376 
01377 //              TRACEUSER("Gerry", _T("KernelTargetWindow = %s"), TargetWindow->GetClassInfo()->GetClassName());
01378                 wxRect TargetRect = TargetWindow->GetRect();
01379 //              TRACEUSER("Gerry", _T("TargetRect = (%d, %d) [%d, %d]"), TargetRect.x, TargetRect.y, TargetRect.width, TargetRect.height);
01380                 if (TargetWindow->GetParent() && !TargetWindow->IsTopLevel())
01381                 {
01382                     TargetWindow->GetParent()->ClientToScreen(&TargetRect.x, &TargetRect.y);
01383 //                  TRACEUSER("Gerry", _T("TargetRect = (%d, %d) [%d, %d]"), TargetRect.x, TargetRect.y, TargetRect.width, TargetRect.height);
01384                 }
01385 
01386 //              TRACEUSER("Gerry", _T("Point is %sinside"), TargetRect.Inside(WinoilMousePos) ? _T("") : _T("not "));
01387 
01388                 if (BroadcastToAll || Ptr->WantsAllEvents() ||
01389                     TargetRect.Inside(WinoilMousePos))
01390                 {
01391                     // Determine if the pointer is over the target window, or any of its children
01392                     wxWindow* WindowUnderPoint = wxChildWindowFromPoint(WinoilMousePos, false, -1);
01393                     BOOL AreOverTargetWnd = (WindowUnderPoint == TargetWindow);
01394                     
01395                     if (!AreOverTargetWnd)
01396                     {
01397                         // We're not immediately over the background of the window, but may be over
01398                         // a child-window of our window! The subtlety here is that wxChildWindowFromPoint may have
01399                         // failed because another window is on top (in the way). So we also check the child window
01400                         // of the target window which is under the mousepointer is also the window which is
01401                         // under the mouse pointner
01402                         wxWindow* ChildWindowUnderPoint = ::wxChildWindowFromPoint(TargetWindow, WinoilMousePos, false, -1);
01403                         AreOverTargetWnd = (ChildWindowUnderPoint != NULL &&
01404                                                 ChildWindowUnderPoint == WindowUnderPoint);
01405                     }
01406 
01407                     if (BroadcastToAll || Ptr->WantsAllEvents() || AreOverTargetWnd)
01408                     {
01409                         wxScreenDC dc;
01410                         wxSize ppi = OSRenderRegion::GetFixedDCPPI(dc);
01411 
01412                         KernelMousePos.x = ((WinoilMousePos.x - TargetRect.GetLeft()) * 72000) / ppi.GetWidth();
01413 // CHECKRECT: This may need to be the exclusive bottom coord
01414                         KernelMousePos.y = ((TargetRect.GetBottom() - WinoilMousePos.y) * 72000) / ppi.GetHeight();
01415                     }
01416                     else
01417                         GoAhead = FALSE;
01418                 }
01419                 else
01420                     GoAhead = FALSE;
01421             }
01422 
01423 //          TRACEUSER("Gerry", _T("%s"), GoAhead ? _T("Process") : _T("Skipping"));
01424 
01425             if (GoAhead &&
01426                 Ptr->ProcessEvent(Event, CurrentDragInfo, &KernelMousePos, CurrentKeypress))
01427             {
01428                 CurrentDragTarget = Ptr;
01429                 OverTarget = TRUE;  // This Target claimed the event, so return TRUE
01430 
01431                 if (!BroadcastToAll)
01432                     break;
01433             }
01434         }
01435         else
01436         {
01437             wxWindow* TargetWindow;
01438             wxRect TargetRect;
01439             Ptr->GetTargetAreaInfo(&TargetWindow, &TargetRect);
01440 #if FALSE
01441             if (TargetWindow)
01442             {
01443                 TRACEUSER("Gerry", _T("OilTargetWindow = %s"), TargetWindow->GetClassInfo()->GetClassName());
01444                 TRACEUSER("Gerry", _T("TargetRect = (%d, %d) [%d, %d]"), TargetRect.x, TargetRect.y, TargetRect.width, TargetRect.height);
01445             }
01446             else
01447             {
01448                 TRACEUSER("Gerry", _T("OilTargetWindow = <NONE>"));
01449             }
01450 #endif
01451             wxPoint ClientPoint;                    // This will be screen coords, or will end up as 
01452             ClientPoint.x = WinoilMousePos.x;   // client coords if we have a window... 
01453             ClientPoint.y = WinoilMousePos.y;
01454 
01455             if (TargetWindow != NULL)
01456             {
01457                 // Get the mouse position in client coords
01458                 ClientPoint = TargetWindow->ScreenToClient(ClientPoint);
01459 
01460                 // Don't bother giving the event to targets which don't contain the pointer
01461                 if (BroadcastToAll || Ptr->WantsAllEvents() ||
01462                     TargetRect.Inside(ClientPoint))
01463                 {
01464                     // Don't give the event to oil targets unless the pointer is over the
01465                     // window (ie dont pass on events to overlapped windows) unless we want
01466                     // to broadcast to all, or this target really wants to know!
01467 
01468                     wxWindow* WindowUnderPoint = ::wxChildWindowFromPoint(WinoilMousePos, false, -1);
01469 //                  TRACEUSER("Gerry", _T("WindowUnderPoint = 0x%08x (%s)"), WindowUnderPoint, WindowUnderPoint ? WindowUnderPoint->GetClassInfo()->GetClassName() : _T("null"));
01470                     if (WindowUnderPoint)
01471                     {
01472 //                      TRACEUSER("Gerry", _T("Title = %s"), WindowUnderPoint->GetTitle().c_str());
01473                     }
01474 
01475                     BOOL AreOverTargetWnd = (WindowUnderPoint == TargetWindow);
01476 //                  TRACEUSER("Gerry", _T("Point is %sover target window"), AreOverTargetWnd ? _T("") : _T("not "));
01477 
01478                     if (!AreOverTargetWnd)
01479                     {
01480                         // We're not immediately over the background of the window, but may be over
01481                         // a child-window of our window! The subtlety here is that wxChildWindowFromPoint may have
01482                         // failed because another window is on top (in the way). So we also check the child window
01483                         // of the target window which is under the mousepointer is also the window which is
01484                         // under the mouse pointner
01485                         wxWindow* ChildWindowUnderPoint = ::wxChildWindowFromPoint(TargetWindow, WinoilMousePos, false, -1);
01486 //                      TRACEUSER("Gerry", _T("ChildFromPoint = 0x%08x (%s)"), ChildWindowUnderPoint, ChildWindowUnderPoint ? ChildWindowUnderPoint->GetClassInfo()->GetClassName() : _T("null"));
01487                         AreOverTargetWnd = (ChildWindowUnderPoint != NULL &&
01488                                                 ChildWindowUnderPoint == WindowUnderPoint);
01489 
01490 //                      TRACEUSER("Gerry", _T("Point is %sover child of target window"), AreOverTargetWnd ? _T("") : _T("not "));
01491                     }
01492 
01493                     if (!BroadcastToAll && !Ptr->WantsAllEvents() && !AreOverTargetWnd)
01494                     {
01495                         GoAhead = FALSE;
01496                     }
01497                 }
01498                 else
01499                     GoAhead = FALSE;
01500             }
01501 
01502 //          TRACEUSER("Gerry", _T("%s"), GoAhead ? _T("Process") : _T("Skipping"));
01503 
01504             // we are in a target area, or this is a broadcast-to-all, so send the event
01505             if (GoAhead)
01506             {
01507                 wxPoint PointInWindow(ClientPoint); // "Cast" to wxPoint
01508 
01509                 if (Ptr->ProcessEvent(Event, CurrentDragInfo, &PointInWindow, CurrentKeypress))
01510                 {
01511                     CurrentDragTarget = Ptr;
01512                     OverTarget = TRUE;  // This Target claimed the event, so return TRUE
01513 
01514                     if (!BroadcastToAll)
01515                         break;
01516                 }
01517             }
01518         }
01519 
01520         Ptr = Next;
01521     }
01522 
01523     if (!DragPending && Event != DRAGEVENT_COMPLETED)
01524     { 
01525         SetStatusLineText();
01526         SetCursor();
01527     }   
01528 
01529     return OverTarget;  // Return status to indicate wheteher or not the event was claimed
01530 }
01531 
01532          
01533 
01534 /********************************************************************************************
01535 
01536 >   virtual BOOL DragManagerOp::OnIdleEvent(void)
01537 
01538     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> & Chris
01539     Created:    9/1/95
01540 
01541     Returns:    TRUE if it does not want low-priority idle handlers to be called this time
01542                 FALSE if it's OK to call low-priority idles (i.e. if I'm not busy this turn)
01543 
01544     Purpose:    To process idle events. If the mouse hasn't moved, then we'll allow low
01545                 priority handlers a look-in. This means that (e.g.) when dragging background-
01546                 redrawing galleries, we get instant response while dragging, and the
01547                 background redraw will only occur while the mouse is held still.
01548 
01549 ********************************************************************************************/
01550 
01551 BOOL DragManagerOp::OnIdleEvent(void)
01552 {
01553     LastMousePos = CurrentMousePos;
01554     CurrentMousePos = wxGetMousePosition();
01555 
01556     if(DragEnded)
01557         return(FALSE);  // Done nothing, so let low-priority handlers have a go
01558 
01559     BOOL JustStartedDrag = FALSE;
01560 
01561     // We have received a start drag message but we are not sure whether this is the real 
01562     // thing yet.
01563     if (DragPending)
01564     {
01565         // We start a drag if DragDelay milliseconds have elapsed
01566         // or the pointer has left DragStartRect
01567         if (!DragStartTimer.Elapsed(DragDelay) &&
01568             StillClickRect.Inside(CurrentMousePos))
01569         {
01570             // The drag is still pending
01571             return(FALSE);  // Done nothing, so let low-priority handlers have a go
01572         }
01573 
01574         DragPending = FALSE;
01575         JustStartedDrag = TRUE; // Flag that we have "just turned on" the drag
01576 
01577         TheCaptureHandler->SetUpSolidDrag(CurrentMousePos);
01578     }
01579 
01580     // Determine what event type to send around...
01581     DragEventType Event = DRAGEVENT_MOUSEIDLE;
01582     if (LastMousePos == CurrentMousePos)
01583     {
01584         if (LastEvent == DRAGEVENT_MOUSESTOPPED || LastEvent == DRAGEVENT_MOUSEIDLE)
01585         {
01586             // The mouse has not moved for a while, so send another idle
01587             Event = DRAGEVENT_MOUSEIDLE;
01588         }
01589         else
01590         {
01591             // The mouse has only just stopped moving, so send a mouse-stopped
01592             Event = DRAGEVENT_MOUSESTOPPED;
01593         }
01594     }
01595     else
01596     {
01597         // The mouse has moved since we last checked, so send a mouse-moved
01598         Event = DRAGEVENT_MOUSEMOVED;
01599     }
01600 
01601     // If the mouse moved, then we will not allow low-priority idle processors to have a go
01602     // this time around, for maximum mouse-move interactiveness.
01603     BOOL ClaimTheIdle = (Event == DRAGEVENT_MOUSEMOVED);
01604 
01605 // **** !!!! ToDo: This could be considered bodgy and nasty, mostly because it is.
01606 
01607 // ToDo: Somehow detect if the drag has ended? A bodge I know, but we wanna compile
01608 // this and see if it works!
01609 
01610 if (KeyPress::IsEscapePressed())    // If escape (or equivalent) pressed, abort the drag
01611 {
01612     AbortDrag();
01613     return(FALSE);  // Let low-priority handlers have a go
01614 }
01615 
01616 // **** 
01617 
01618     ProcessEvent(Event);    // Pass the event around all registered DragTargets
01619 
01620 #if FALSE
01621 /* On the first update, the mouse may not have moved, so we need to pop up the
01622    solid drag stuff. Unfortunately, this doesn't work quite right and I don't
01623    have time to deal with it right now.
01624 
01625     if (!DragEnded && JustStartedDrag)
01626     {
01627         // The mouse may not have moved, but we have just 'turned on' the drag - we'd
01628         // better ensure that the solid drag stuff is drawn onto screen for the fist time
01629 
01630         if (TheCaptureWindow != NULL)
01631         {
01632             CPoint PointInCaptureWnd(CurrentMousePos);
01633 
01634             // Convert the current mouse coordinate into capture window client coords,
01635             // and call it to update the solid drag
01636             TheCaptureWindow->ScreenToClient(&PointInCaptureWnd);
01637             TheCaptureWindow->DrawSolidDrag(PointInCaptureWnd);
01638         }
01639     }
01640 */
01641 #endif
01642 
01643     return(ClaimTheIdle);   // Return, allowing or not-allowing low-priority handlers to have a go
01644                             // depending on whether the mouse moved or not.
01645 }
01646 
01647 
01648 
01649 /********************************************************************************************
01650 
01651 >   void DragManagerOp::RegisterTarget(DragTarget *NewTarget, BOOL HighPriority = FALSE)
01652 
01653     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01654     Created:    9/1/95
01655 
01656     Inputs:     NewTarget - points at the DragTarget object to add. NOTE that from this
01657                 time on, the manager owns the target, and it will delete it when the drag
01658                 completes. However, the caller may delete the target at any time, in which
01659                 case it will automatically deregister itself before it dies.
01660 
01661                 HighPriority - TRUE to place the target on the front of the target list,
01662                 FALSE to place it on the end. (Targets are called in list order to handle
01663                 events, so one on the front of the list has higher priority...)
01664 
01665     Purpose:    To register a Drag Target with the current Drag Manager
01666                 This method is automatically called by DragTargets when they are
01667                 constructed, and is only available to frined classes.
01668 
01669     Notes:      A drag target object can be registered several times, in which case it will
01670                 be placed on the list several times. Not that this should happen...
01671 
01672     Scope:      protected (for friend class DragTarget only)
01673 
01674 ********************************************************************************************/
01675 
01676 void DragManagerOp::RegisterTarget(DragTarget *NewTarget, BOOL HighPriority)
01677 {
01678     ERROR3IF(NewTarget == NULL,
01679                 "DragManagerOp::RegisterTarget - NULL Target parameter is illegal");
01680 
01681     if (HighPriority)
01682         Targets.AddHead(NewTarget);
01683     else
01684         Targets.AddTail(NewTarget);
01685 }
01686 
01687 
01688 
01689 /********************************************************************************************
01690 
01691 >   void DragManagerOp::DeregisterTarget(DragTarget *OldTarget)
01692 
01693     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01694     Created:    9/1/95
01695 
01696     Inputs:     OldTarget - points at the DragTarget object to remove
01697 
01698     Purpose:    To register a Drag Target with the current Drag Manager
01699                 This method is automatically called by DragTargets when they are
01700                 constructed, and is only available to frined classes.
01701 
01702     Notes:      Copes with a drag target being registered several times.
01703 
01704     Scope:      protected (for friend class DragTarget only)
01705 
01706 ********************************************************************************************/
01707 
01708 void DragManagerOp::DeregisterTarget(DragTarget *OldTarget)
01709 {
01710     DragTarget *Ptr = (DragTarget *) Targets.GetHead();
01711     DragTarget *Next;
01712 
01713     while (Ptr != NULL)
01714     {
01715         Next = (DragTarget *) Targets.GetNext(Ptr);
01716 
01717         if (Ptr == OldTarget)
01718         {
01719             Targets.RemoveItem(Ptr);
01720             delete Ptr;
01721         }
01722 
01723         Ptr = Next;
01724     }
01725 }
01726 
01727 
01728 
01729 /********************************************************************************************
01730 
01731 >   void DragManagerOp::CleanUpAfterDrag(void)
01732 
01733     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01734     Created:    9/1/95
01735 
01736     Purpose:    Generic clean-up method. Deletes all registered DragTargets, and any
01737                 other information (DragInformation, last keypress info, etc) which is
01738                 still lying about in the DragManagerOp.
01739                 Also deregisters our idle event handlers etc.
01740                 Used by destructor, and also by all forms of Drag completion to free
01741                 our memory claims, etc.
01742 
01743     Scope:      private
01744 
01745 ********************************************************************************************/
01746 
01747 void DragManagerOp::CleanUpAfterDrag(void)
01748 {
01749     TRACEUSER("Gerry", _T("DragManagerOp::CleanUpAfterDrag"));
01750 
01751     GetApplication()->RemoveIdleProcessor(IDLEPRIORITY_HIGH, this);
01752 
01753     if (TheCaptureHandler != NULL)
01754     {
01755         TRACEUSER("Gerry", _T("Deleting TheCaptureHandler"));
01756         // Simply delete the CaptureHandler and it will detach itself
01757         delete TheCaptureHandler;
01758         TheCaptureHandler = NULL;
01759     }
01760 
01761     if (CurrentDragInfo != NULL)
01762     {
01763         delete CurrentDragInfo;
01764         CurrentDragInfo = NULL;
01765     }
01766 
01767     if (CurrentKeypress != NULL)
01768     {
01769         delete CurrentKeypress;
01770         CurrentKeypress = NULL;
01771     }
01772 
01773     // Delete all entries from the list. We do it this way to ensure that we don't try
01774     // to destruct the same target multiple times if it registered multiple times
01775     while (!Targets.IsEmpty())
01776         DeregisterTarget((DragTarget *) Targets.GetHead());
01777 }
01778 
01779 
01780 
01781 /********************************************************************************************
01782 
01783 >   void DragManagerOp::SetCursor()
01784 
01785     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
01786     Created:    15/1/95
01787     Returns:    -
01788     Purpose:    Set the cursor !
01789    
01790 ********************************************************************************************/
01791 
01792 void DragManagerOp::SetCursor()
01793 {
01794     UINT32 CursorID;
01795 
01796     // are we over a target ??
01797     if(CurrentDragTarget== NULL)
01798       CursorID = CurrentDragInfo->GetCursorID();    // nope
01799     else
01800       CursorID = CurrentDragTarget->GetCursorID();  // yep
01801     
01802     // the target does not want to change the cursor
01803     if(CursorID == 0)
01804         return;
01805     
01806     if(CurrentManager->CurrentID != CursorID)                       // nothing to change
01807     {
01808         if(CurrentManager->CurrentCursor)                           // delete the old
01809         {
01810             delete CurrentManager->CurrentCursor;
01811             CurrentManager->CurrentCursor = NULL;
01812         }
01813         if(CurrentManager->CurrentCursor==NULL)
01814         {
01815             CurrentManager->CurrentCursor = new Cursor(CursorID);   // create the new
01816             if (CurrentManager->CurrentCursor)
01817                 CurrentManager->CurrentCursor->SetActive();         // make the active cursor
01818         }
01819         
01820         CurrentManager->CurrentID = CursorID;
01821     }
01822 }
01823 
01824 
01825 /********************************************************************************************
01826 
01827 >   void DragManagerOp::SetStatusLineText()
01828 
01829     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
01830     Created:    15/1/95
01831     Returns:    -
01832     Purpose:    Write Status line help
01833    
01834 ********************************************************************************************/
01835 
01836 void DragManagerOp::SetStatusLineText()
01837 {
01838     String_256 StatusText;
01839     if(CurrentDragTarget==NULL) //we are not over a target
01840     {   // get the drag status text
01841         if(CurrentDragInfo)
01842             if(CurrentDragInfo->GetStatusLineText(&StatusText))
01843                 GetApplication()->UpdateStatusBarText(&StatusText,FALSE); 
01844     }
01845     else
01846     {   // get the target status text
01847         if(CurrentDragTarget->GetStatusLineText(&StatusText))
01848             GetApplication()->UpdateStatusBarText(&StatusText,FALSE); 
01849     }
01850             
01851 
01852 }
01853 
01854 
01855 /********************************************************************************************
01856 
01857 >   virtual BOOL DragManagerOp::GetStatusText(String_256 * StatusText)
01858 
01859     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
01860     Created:    22/11/94
01861     Inputs:     -
01862     Outputs:    -
01863     Returns:    TRUE if the buffer is valid FALSE otherwise
01864     Purpose:    put status text in a buffer
01865     Errors:     -
01866     SeeAlso:    -
01867 
01868 ********************************************************************************************/
01869 
01870 BOOL DragManagerOp::GetStatusText(String_256 * StatusText)
01871 {
01872     ERROR2IF(StatusText==NULL,FALSE,"DragManagerOp::GetStatusLineText() - StatusText==NULL!");
01873 
01874     String_256 Text;
01875     if(CurrentDragTarget)
01876     {
01877         if(CurrentDragInfo->GetStatusLineText(&Text))
01878             * StatusText = Text;
01879         else
01880             return FALSE;
01881     }
01882     else
01883     {
01884         if(CurrentDragTarget->GetStatusLineText(&Text))
01885            * StatusText = Text;
01886         else
01887             return FALSE;
01888     }
01889         
01890     return TRUE; 
01891 
01892 }
01893 
01894 
01895 
01896 /********************************************************************************************
01897 
01898 >   void DragManagerOp::RedrawStarting()
01899 
01900     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01901     Created:    27/3/95
01902     Returns:    -
01903     Purpose:    Tell the drag manager that an external redraw has started.
01904                 This allows it to remove its solid drag stuff so that the screen display is
01905                 not screwed up. You should also call RedrawFinished when you finish redrawing
01906 
01907     Notes:      If you are redrawing in a particular window & gadget, see the other variant
01908                 of this method, which will reduce solid-drag flicker.
01909 
01910     SeeAlso:    DragManagerOp::RedrawFinished()
01911 
01912 ********************************************************************************************/
01913 
01914 void DragManagerOp::RedrawStarting()
01915 {
01916     if (RedrawInProgress)
01917         return;
01918 
01919     RedrawInProgress = TRUE;
01920 
01921     if (DragManagerOp::CurrentManager &&
01922         DragManagerOp::CurrentManager->CurrentDragInfo &&
01923         DragManagerOp::CurrentManager->CurrentDragInfo->DoesSolidDrag)
01924     {
01925         DragManagerOp::CurrentManager->TheCaptureHandler->CleanUpSolidDrag();
01926     }
01927 }
01928 
01929 
01930 
01931 /********************************************************************************************
01932 
01933 >   static void DragManagerOp::RedrawStarting(CWindowID TheWindow, CGadgetID TheGadget,
01934                                                 DocRect *TheArea = NULL)
01935 
01936     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01937     Created:    8/5/95
01938 
01939     Inputs:     TheWindow - The CWindowID of your DialogOp
01940                 TheGadget - The Gadget ID of the gadget  being redrawn
01941                 TheArea - A kernel-rendered dialogue rectangle (MILLIPOINTS) which is being
01942                 redrawn. If NULL, the entire gadget is assumed. NOTE that this is clipped
01943                 within the gadget bounds, so may be outside the 'visible area' of the gadget
01944 
01945 
01946     Returns:    -
01947     Purpose:    Tell the drag manager that an external redraw has started, within a specific
01948                 window and gadget.
01949 
01950                 This allows it to remove its solid drag stuff so that the screen display is
01951                 not screwed up. You should also call RedrawFinished when you finish redrawing
01952 
01953                 This call specifies a particular gadget that is redrawing - if this doesn't
01954                 overlap the solid drag area, then nothing will be done - this will reduce
01955                 flicker if you're background redrawing while a drag is going on.
01956 
01957     SeeAlso:    DragManagerOp::RedrawFinished()
01958 
01959 ********************************************************************************************/
01960 
01961 void DragManagerOp::RedrawStarting(CWindowID TheWindow, CGadgetID TheGadget, DocRect *TheArea)
01962 {
01963     if (RedrawInProgress)
01964         return;
01965 
01966     if (DragManagerOp::CurrentManager &&
01967         DragManagerOp::CurrentManager->CurrentDragInfo &&
01968         DragManagerOp::CurrentManager->CurrentDragInfo->DoesSolidDrag)
01969     {
01970         wxWindow* pWindow = (wxWindow*)TheWindow;
01971         wxWindow* pGadget = pWindow->FindWindow((INT32)TheGadget);
01972         if (pGadget != NULL)
01973         {
01974             wxRect AreaClientRect;
01975             wxRect ClientRect;
01976             if (TheArea != NULL)
01977             {
01978                 ReDrawInfoType DlgInfo;
01979                 DialogManager::GetKernelRenderedGadgetInfo(TheWindow, TheGadget, &DlgInfo);
01980 
01981                 INT32 PixelSize = 72000 / DlgInfo.Dpi;      // Size of a pixel in MILLIPOINTS
01982                 AreaClientRect.x        = TheArea->lo.x / PixelSize;
01983                 AreaClientRect.y        = TheArea->hi.x / PixelSize;
01984                 AreaClientRect.width    = TheArea->Width() / PixelSize;
01985                 AreaClientRect.height   = TheArea->Height() / PixelSize;
01986             }
01987             else
01988                 AreaClientRect = pGadget->GetClientRect();
01989 
01990             ClientRect = pGadget->GetClientRect();
01991 
01992             wxRect ScreenRect(ClientRect);
01993 
01994             // Get the intersection of the rects (clip the redrawing area within the window)
01995             if (!ScreenRect.Intersect(AreaClientRect).IsEmpty())
01996             {
01997                 // Convert the client coordinates to screen coords, and tell the drag capture window
01998                 // to get it's solid drag stuff out of the way
01999                 pGadget->ClientToScreen(&ScreenRect.x, &ScreenRect.y);
02000 
02001                 RedrawInProgress = DragManagerOp::CurrentManager->TheCaptureHandler->
02002                                                     CleanUpSolidDragInScreenArea(ScreenRect);
02003             }
02004             else
02005                 RedrawInProgress = FALSE;
02006         }
02007         else
02008         {
02009             // We failed to get the window area, so we'll have to clean up just in case
02010             DragManagerOp::CurrentManager->TheCaptureHandler->CleanUpSolidDrag();
02011             RedrawInProgress = TRUE;
02012         }
02013     }   
02014 }
02015 
02016 
02017 /********************************************************************************************
02018 
02019 >   void DragManagerOp::RedrawFinished()
02020 
02021     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
02022     Created:    27/3/95
02023     Returns:    -
02024     Purpose:    Tell the drag manager that an external redraw has finished.
02025    
02026 ********************************************************************************************/
02027 
02028 void DragManagerOp::RedrawFinished()
02029 {
02030     if (!RedrawInProgress)
02031         return;
02032 
02033     RedrawInProgress = FALSE;
02034 
02035     if (DragManagerOp::CurrentManager &&
02036         DragManagerOp::CurrentManager->CurrentDragInfo &&
02037         DragManagerOp::CurrentManager->CurrentDragInfo->DoesSolidDrag)
02038     {
02039         wxPoint LastMousePos = DragManagerOp::CurrentManager->GetDragMousePos();
02040         DragManagerOp::CurrentManager->TheCaptureHandler->SetUpSolidDrag(LastMousePos);
02041     }
02042 }

Generated on Sat Nov 10 03:48:25 2007 for Camelot by  doxygen 1.4.4