00001 // $Id: camview.cpp 1743 2006-09-06 09:32:51Z alex $ 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 #include "camtypes.h" 00099 00100 #include "camview.h" 00101 00102 #include "camelot.h" 00103 #include "camframe.h" 00104 #include "camdoc.h" 00105 #include "vstate.h" 00106 #include "ccdc.h" 00107 #include "csrstack.h" 00108 00109 #include "rendwnd.h" 00110 //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00111 #include "prntview.h" 00112 #include "osrndrgn.h" 00113 #include "scroller.h" 00114 #include "rulers.h" 00115 //#include "bars.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00116 #include "localenv.h" 00117 #include "zoomops.h" 00118 #include "vkextra.h" 00119 #include "brushmsg.h" 00120 #include "statline.h" 00121 #include "draginfo.h" 00122 #include "prdlgctl.h" 00123 #include "prncamvw.h" 00124 #include "opbevel.h" 00125 #include "psrndrgn.h" 00126 #include "prnmks.h" 00127 #include "princomp.h" 00128 #include "oilruler.h" 00129 #include "strlist.h" 00130 #include "impexpop.h" 00131 00132 /***************************************************************************************************************************/ 00133 00134 IMPLEMENT_DYNAMIC_CLASS( CCamView, wxView ) 00135 CC_IMPLEMENT_DYNAMIC( ViewDragTarget, OilDragTarget ) 00136 CC_IMPLEMENT_DYNCREATE( PageDropInfo, CCObject ) 00137 00138 // Declare smart memory handling in Debug builds 00139 #define new CAM_DEBUG_NEW 00140 00141 // This user preference controls how many pixels the mouse must move before a 00142 // drag is initiated. 00143 INT32 CCamView::DragLatency = 3; 00144 00145 INT32 CCamView::s_MouseMoveEliminationPeriod = 0; 00146 00147 // Used to start drags after user has clicked but not moved mouse for n milliseconds. 00148 INT32 CCamView::DragDelay = 500; 00149 MonotonicTime CCamView::DragTimer; 00150 00151 INT32 CCamView::PopCount = 0; 00152 ViewState* CCamView::pReadyMadeViewState = NULL; 00153 BOOL CCamView::DefaultScrollersState = TRUE; 00154 BOOL CCamView::DefaultRulersState = FALSE; 00155 BOOL CCamView::UseVisibleDefaults = TRUE; 00156 00157 // Default to a nonsense size. Will be fixed up in OnSize 00158 INT32 CCamView::ScrollBarSize = 1; 00159 00160 BEGIN_EVENT_TABLE( CCamView, wxView ) 00161 EVT_SIZE(CCamView::OnSize) 00162 EVT_SCROLL(CCamView::OnScroll) 00163 EVT_TIMER(DragIdleID, CCamView::OnDragIdle) 00164 END_EVENT_TABLE() 00165 00166 /********************************************************************************************* 00167 00168 > CCamView::CCamView() 00169 00170 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00171 Created: ages ago 00172 Inputs: - 00173 Outputs: - 00174 Returns: - 00175 Purpose: Default constructor for a CCamView window. Sets the pointers to the 00176 child windows to null, so that an incomplete construction of the view 00177 that is later destroyed won't try to delete invalid pointers. The 00178 Windows side of construction is done later, in the OnCreate() message 00179 handler. 00180 00181 Updates the CCamView population counter. Called from somewhere deep 00182 inside MFC. 00183 Errors: - 00184 Scope: Protected. 00185 SeeAlso: CCamView::OnCreate(); CCamView::~CCamView() 00186 00187 **********************************************************************************************/ 00188 00189 CCamView::CCamView() 00190 { 00191 TRACEUSER("Gerry", _T("Creating CCamView at 0x%08x\n"), this); 00192 00193 // No child windows or connections yet. 00194 pDocView = NULL; 00195 pPrintView = NULL; 00196 00197 // Create a ViewState object to maintain device-independent information. 00198 Status = new ViewState; 00199 00200 RenderWindow = NULL; 00201 HScrollBar = NULL; 00202 VScrollBar = NULL; 00203 Corner = NULL; 00204 HRuler = NULL; 00205 VRuler = NULL; 00206 OGadget= NULL; 00207 00208 // Set/clear these internal flags. 00209 fSetupDone = FALSE; 00210 fInitialUpdate = FALSE; 00211 00212 // Not dragging or scrolling either. 00213 pCurrentDragOp = NULL; 00214 00215 OLERecaptureMouse = FALSE; 00216 00217 // Set up click event variables 00218 LastClickType = CLICKTYPE_NONE; 00219 LastClickButton = 0; 00220 LastClickPoint.x = 0; 00221 LastClickPoint.y = 0; 00222 CurrentMousePos.x = 0; 00223 CurrentMousePos.y = 0; 00224 FirstClickButton = 0; 00225 DragKeepAccuracy = TRUE; 00226 AutoScrollExcludeRulers = FALSE; 00227 00228 // Bump the population. 00229 PopCount++; 00230 00231 // Vars used by InvokeDragOp() mechanism 00232 DragOpToken = ""; 00233 pDragOpParam = NULL; 00234 DragOpInvoke = FALSE; 00235 00236 // Set up the drag idle timer 00237 m_DragIdleTimer.SetOwner(this, DragIdleID); 00238 00239 // Triple and quad click support 00240 LastDoubleClickPos = wxPoint( 0, 0 ); 00241 ThisSingleIsTriple = FALSE; 00242 ThisDoubleIsQuad = FALSE; 00243 00244 // Set this flag until we have been through OnActivateView once, after which we can 00245 // include this view in the eat-activating-click system. 00246 fJustCreated = TRUE; 00247 00248 // Mouse move handling 00249 m_LastMouseState=0; 00250 m_LastMousePosition=wxDefaultPosition; 00251 m_LastMouseUsedTimestamp=0; 00252 m_CouldSkipNextMouse=FALSE; 00253 00254 OldOffset = WorkCoord(0, 0); // need to initialize it to something 00255 } 00256 00257 /********************************************************************************************* 00258 > virtual CCamView::~CCamView() 00259 00260 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00261 Created: ages ago 00262 Inputs: - 00263 Outputs: - 00264 Returns: - 00265 Purpose: Destroys a CCamView window. Deletes child windows first. 00266 Updates the CCamView population counter. 00267 Errors: - 00268 Scope: Public 00269 SeeAlso: CCamView::CCamView() 00270 00271 **********************************************************************************************/ 00272 00273 CCamView::~CCamView() 00274 { 00275 TRACEUSER("Gerry", _T("Deleting CCamView at 0x%08x\n"), this); 00276 00277 PopCount--; // one less ScreenView in the world, sigh 00278 00279 if(pDocView != NULL) 00280 delete pDocView; 00281 00282 if(Status != NULL) 00283 delete Status; 00284 00285 pDocView = NULL; 00286 Status = NULL; 00287 00288 // We shouldn't have a print view here! 00289 if (pPrintView != NULL) 00290 { 00291 ERROR3("CCamView is dying when it still has a PrintView attached!"); 00292 delete pPrintView; 00293 } 00294 } 00295 00296 /*********************************************************************************************/ 00297 00298 // What to do when a view is created. Creates actual 00299 // windows for displaying the view. 00300 bool CCamView::OnCreate( wxDocument *pDoc, /* TYPENOTE: Correct */ long flags ) 00301 { 00302 TRACEUSER("Gerry", _T("CCamView::OnCreate at 0x%08x\n"), this); 00303 00304 // Construct the (C++) child windows. 00305 RenderWindow = new CRenderWnd(this); 00306 HScrollBar = new CWinScroller(TRUE); 00307 VScrollBar = new CWinScroller(FALSE); 00308 PORTNOTE("other","ScreenCamView::OnCreate - Removed scroller corner usage") 00309 #ifndef EXCLUDE_FROM_XARALX 00310 Corner = new CScrollerCorner; 00311 #endif // EX_LX 00312 HRuler = new OILHorizontalRuler; 00313 VRuler = new OILVerticalRuler; 00314 OGadget = new OriginGadget; 00315 if (!RenderWindow 00316 || !HScrollBar 00317 || !VScrollBar 00318 #ifndef EXCLUDE_FROM_XARALX 00319 || !Corner 00320 #endif // EX_LX 00321 || !HRuler ||!VRuler ||!OGadget 00322 ) 00323 { 00324 Error::SetError(_R(IDE_CREATE_VIEW_FAILED), 0); 00325 InformError(); 00326 return false; 00327 } 00328 00329 m_pFrame = wxGetApp().CreateChildFrame( pDoc, this ); 00330 m_pFrame->SetTitle(_T("DrawingView")); 00331 00332 INT32 width, height; 00333 m_pFrame->GetClientSize( &width, &height ); 00334 00335 // Now do the other half of the construction. The stated sizes and 00336 // positions of the windows here will be changed very soon. 00337 const WinRect rcARect(-100,-100,-90,-90); 00338 if (!RenderWindow->Create(rcARect, m_pFrame, WID_RENDERWINDOW) 00339 || !HScrollBar->Create(m_pFrame, WID_HSCROLLBAR, wxPoint(-100, -100)) 00340 || !VScrollBar->Create(m_pFrame, WID_VSCROLLBAR, wxPoint(-100, -100)) 00341 // || !Corner->Create("", "", 0, rcARect, this, WID_SIZECORNER) 00342 || !HRuler->Create(this, WID_HRULER) 00343 || !VRuler->Create(this, WID_VRULER) 00344 || !OGadget->Create(this, WID_RULERORIGIN) 00345 ) 00346 { 00347 Error::SetError(_R(IDE_CREATE_VIEW_FAILED), 0); 00348 InformError(); 00349 return false; 00350 } 00351 00352 CreateNewDocView(); 00353 00354 CViewFileDropTarget* pTarget = new CViewFileDropTarget(this); 00355 if (pTarget) 00356 RenderWindow->SetDropTarget(pTarget); 00357 00358 // init the kernel rulers and establish pointer links to them 00359 RulerPair* pRulers=pDocView->GetpRulerPair(); 00360 pRulers->Init(pDocView,HRuler,VRuler,OGadget); 00361 HRuler->LinkToKernel(pRulers->GetpHorizontalRuler()); 00362 VRuler->LinkToKernel(pRulers->GetpVerticalRuler()); 00363 ENSURE(pDocView != 0, "CCamView::ScreenView can't get a new DocView!"); 00364 pDocView->ConnectToOilView(this); 00365 00366 // find the last view so we can use some of it's settings to create the new 00367 // DocView * LastView = DocView::GetSelected(); 00368 00369 // Link this and the DocView to the ViewState object. 00370 pDocView->SetViewState(Status); 00371 00373 00374 wxScreenDC dc; 00375 wxSize pixsize=OSRenderRegion::GetFixedDCPPI(dc); 00376 00377 // Tell DocView how big the pixel size is. 00378 FIXED16 PixelWidth = FIXED16(72000.0/pixsize.x); 00379 FIXED16 PixelHeight = FIXED16(72000.0/pixsize.y); 00380 ERROR3IF(PixelWidth != PixelHeight, "Luke says non-square pixels are not supported"); 00381 pDocView->SetPixelSize(PixelWidth, PixelHeight); 00382 00383 // Make our DocView the current DocView 00384 pDocView->SetCurrent(); 00385 00386 if (GetFrame()) 00387 GetFrame()->GetClientSize(&CurrentSize.width,&CurrentSize.height); 00388 // Now the scrollers have all their information, we can set their appearance. 00389 // Make sure that they are invisible until the rest of the frame is ready 00390 /* XLONG x1 = CurrentSize.GetWidth () * PixelWidth; 00391 XLONG x2 = CurrentSize.GetHeight() * PixelHeight; 00392 GetFrame()->SetScrollbar(wxHORIZONTAL,0,x1,Status->WorkAreaExtent.hi.x-Status->WorkAreaExtent.lo.x,false); 00393 GetFrame()->SetScrollbar( wxVERTICAL,0,x2,Status->WorkAreaExtent.hi.y-Status->WorkAreaExtent.lo.y,false); 00394 */ 00395 00396 ShowScrollers(DefaultScrollersState); 00397 ShowRulers(DefaultRulersState); 00398 00400 00401 // Register for WM_DROPFILES messages 00402 // DragAcceptFiles(TRUE); 00403 00405 00406 // now that the ScreenView (and hence DocView) is stable, broadcast a message to let everyone know 00407 BROADCAST_TO_ALL(DocViewMsg(pDocView,DocViewMsg::NEWANDSTABLE)); 00408 00409 #ifdef __X__ 00410 // X seems to require a forced resize 00411 m_pFrame->SetSize(wxDefaultCoord, wxDefaultCoord, width, height); 00412 #endif 00413 m_pFrame->Show(true); 00414 00415 // This has been removed as it causes the problem where loaded documents 00416 // don't render correctly if a wxYield happens before the document has 00417 // finished loading. It may be possible to rewrite the handling in this 00418 // class so that the order of activation and OnInitialUpdate is not important 00419 // but efforts so far have been in vain. 00420 // The view seems to be activated correctly in any case so hopefully it 00421 // should not be necessary 00422 // Activate(true); 00423 00424 TRACEUSER("Gerry", _T("Leaving CCamView::OnCreate at 0x%08x\n"), this); 00425 00426 return true; 00427 } 00428 00429 /*********************************************************************************************/ 00430 00431 // Clean up windows used for displaying the view. 00432 bool CCamView::OnClose( bool fDeleteWindow /*= TRUE*/ ) 00433 { 00434 TRACEUSER("Gerry", _T("CCamView::OnClose at 0x%08x\n"), this); 00435 00436 if( !GetDocument()->Close() ) 00437 return false; 00438 00439 SetFrame( (wxFrame *)NULL ); 00440 00441 Activate( false ); 00442 00443 if( fDeleteWindow ) 00444 { 00445 TRACEUSER("Gerry", _T("CCamView::OnClose deleting frame at 0x%08x\n"), m_pFrame); 00446 m_pFrame->Show( false ); 00447 00448 delete m_pFrame; 00449 m_pFrame = NULL; 00450 00451 // This will also have deleted the child windows of the frame making our 00452 // pointers invalid so vape them here 00453 RenderWindow = NULL; 00454 HScrollBar = NULL; 00455 VScrollBar = NULL; 00456 00457 #ifndef EXCLUDE_FROM_XARALX 00458 Corner = NULL; 00459 #endif // EX_LX 00460 HRuler = NULL; 00461 VRuler = NULL; 00462 OGadget = NULL; 00463 00464 } 00465 00466 return true; 00467 } 00468 00469 /******************************************************************************************** 00470 > static BOOL CCamView::ReadViewPrefs() 00471 00472 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00473 Created: 26/11/93 00474 Inputs: - 00475 Outputs: - 00476 Returns: TRUE if the .INI file settings were loaded (or created) successfully. 00477 Purpose: Tries to load preferences for CCamView, creating them with default values 00478 if they don't exist. 00479 Errors: - 00480 SeeAlso: Application::DeclareSection; Application::DeclarePref 00481 ********************************************************************************************/ 00482 00483 BOOL CCamView::ReadViewPrefs() 00484 { 00485 // Declare and load the .INI file settings. 00486 BOOL ok = Camelot.DeclareSection(TEXT("Mouse"), 10) && 00487 Camelot.DeclarePref(TEXT("Mouse"), TEXT("DragLatency"), 00488 &CCamView::DragLatency, 1, 10) && 00489 Camelot.DeclarePref(TEXT("Mouse"), TEXT("DragDelay"), 00490 &CCamView::DragDelay, 100, 2000) && 00491 Camelot.DeclarePref(TEXT("Mouse"), TEXT("MoveEliminationPeriod"), 00492 &CCamView::s_MouseMoveEliminationPeriod, 0, 1000) && 00493 00494 Camelot.DeclareSection(TEXT("WindowFurniture"), 10) && 00495 #ifndef EXCLUDE_FROM_XARALX 00496 Camelot.DeclarePref(TEXT("WindowFurniture"), TEXT("PropScrollers"), 00497 &CCamView::PropScrollersOn, FALSE, TRUE) && 00498 #endif 00499 Camelot.DeclarePref(TEXT("WindowFurniture"), TEXT("ScrollersVisibiltyState"), 00500 &CCamView::DefaultScrollersState, FALSE, TRUE)&& 00501 Camelot.DeclarePref(TEXT("WindowFurniture"), TEXT("RulersVisibiltyState"), 00502 &CCamView::DefaultRulersState, FALSE, TRUE) && 00503 00504 #ifndef EXCLUDE_FROM_XARALX 00505 Camelot.DeclareSection(TEXT("Windows"), 10) && 00506 Camelot.DeclarePref(TEXT("Windows"), TEXT("UnzoomOnNewView"), 00507 &CCamView::UnzoomOnNewView, FALSE, TRUE) && 00508 Camelot.DeclarePref(TEXT("Windows"), TEXT("ZoomSingleView"), 00509 &CCamView::ZoomSingleView, FALSE, TRUE) && 00510 #endif 00511 TRUE ; 00512 00513 return ok; 00514 } 00515 00517 // Interface to the kernel's DocView and Document. 00518 00519 /********************************************************************************************* 00520 > CCamDoc* CCamView::GetDocument() const 00521 00522 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00523 Created: ages ago 00524 Inputs: - 00525 Outputs: - 00526 Returns: A pointer to the CCamDoc object associated with this CCamView. 00527 Purpose: Mainly used by MFC. 00528 Errors: ASSERTion failure if CCamView::m_pDocument does not point to 00529 a CCamDoc. 00530 Scope: Public 00531 SeeAlso: class CCamDoc; DocView::GetDocument 00532 **********************************************************************************************/ 00533 00534 CCamDoc* CCamView::GetDocument() const 00535 { 00536 ENSURE( m_viewDocument->IsKindOf( CLASSINFO(CCamDoc) ), 00537 "CCamView::GetDocument: Document is not a Camelot document"); 00538 return (CCamDoc *)m_viewDocument; 00539 } 00540 00541 00542 00543 /********************************************************************************************* 00544 > BOOL CCamView::CreateNewDocView() 00545 00546 Author: Chris_Parks (Xara Group Ltd) <camelotdev@xara.com> 00547 Created: 16/6/96 00548 Inputs: - 00549 Outputs: - 00550 Returns: Success/Fail 00551 Purpose: Creates a new attached DocView - overridden in RalphView 00552 to avoid the no Document problem. 00553 00554 **********************************************************************************************/ 00555 00556 BOOL CCamView::CreateNewDocView() 00557 { 00558 00559 Document* KernelDoc = GetDocument()->GetKernelDoc(); 00560 pDocView = KernelDoc->GetNewDocView(); 00561 return TRUE; 00562 00563 } 00564 00565 /******************************************************************************************** 00566 > ViewState* CCamView::GetViewState() const 00567 00568 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00569 Created: 29/3/94 00570 Inputs: - 00571 Outputs: - 00572 Returns: A pointer to the ViewState shared between this CCamView with a DocView. 00573 Purpose: Allows access to the platform-independent description of a view. 00574 Errors: - 00575 SeeAlso: DocView::SetViewState 00576 ********************************************************************************************/ 00577 00578 ViewState* CCamView::GetViewState() const 00579 { 00580 ENSURE(Status != NULL, "Null ViewState* in CCamView::GetViewState"); 00581 return Status; 00582 } 00583 00584 00585 00586 /******************************************************************************************** 00587 > void CCamView::SetViewState(ViewState* pvs) 00588 00589 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00590 Created: 25/9/95 00591 Inputs: pvs the new view-state 00592 Returns: pointer to the old view-state 00593 Purpose: Sets this CCamView's shared ViewState object. 00594 SeeAlso: CCamView::GetViewState 00595 ********************************************************************************************/ 00596 00597 ViewState* CCamView::SetViewState(ViewState* pvs) 00598 { 00599 ViewState* pvsOld = Status; 00600 Status = pvs; 00601 if (pvsOld->pView != NULL) pvsOld->pView->SetViewState(Status); 00602 return pvsOld; 00603 } 00604 00605 00606 00607 /******************************************************************************************** 00608 > void CCamView::SetCurrentStates() 00609 00610 Author: Chris_Parks (Xara Group Ltd) <camelotdev@xara.com> 00611 Created: 15/6/96 00612 Inputs: - 00613 Purpose: Set the View and Document current 00614 SeeAlso: 00615 ********************************************************************************************/ 00616 00617 void CCamView::SetCurrentStates() 00618 { 00619 if(pDocView) 00620 { 00621 pDocView->SetCurrent(); 00622 Document* KernelDoc = pDocView->GetDoc(); 00623 if(KernelDoc) 00624 KernelDoc->SetCurrent(); 00625 } 00626 } 00627 00629 // Painting. 00630 00631 /******************************************************************************************** 00632 00633 > CNativeDC* CCamView::GetRenderDC() 00634 00635 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 00636 Created: 02/09/95 00637 Returns: pointer to a CNativeDC for rendering into this view 00638 Purpose: Access function for this CCamView's device context. 00639 Errors: - 00640 SeeAlso: - 00641 00642 ********************************************************************************************/ 00643 00644 CNativeDC* CCamView::GetRenderDC() const 00645 { 00646 return RenderWindow?RenderWindow->GetClientDC():NULL; 00647 } 00648 00649 /******************************************************************************************** 00650 00651 > void CCamView::DoneWithDC() 00652 00653 Author: Alex Bligh <alex@alex.org.uk> 00654 Created: 12/06/2006 00655 Purpose: Hints that we've done with our DC 00656 SeeAlso: View; PaperRenderRegion. 00657 00658 Note this is merely a hint. This routine is not guaranteed to eb called 00659 00660 ********************************************************************************************/ 00661 00662 void CCamView::DoneWithDC() const 00663 { 00664 if (RenderWindow) 00665 RenderWindow->DoneWithDC(); 00666 } 00667 00668 /******************************************************************************************** 00669 00670 > void CCamView::AllocateDC() 00671 00672 Author: Alex Bligh <alex@alex.org.uk> 00673 Created: 12/06/2006 00674 Purpose: Hints that we've done with our DC 00675 SeeAlso: View; PaperRenderRegion. 00676 00677 Note this is merely a hint. This routine is not guaranteed to eb called 00678 00679 ********************************************************************************************/ 00680 00681 void CCamView::AllocateDC() const 00682 { 00683 if (RenderWindow) 00684 RenderWindow->AllocateDC(); 00685 } 00686 00687 00688 /********************************************************************************************* 00689 > void CCamView::GetClientSize(int * pWidth, int * pHeight) const TYPENOTE: Correct 00690 00691 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00692 Created: ages ago 00693 Inputs: - 00694 Outputs: The width and height of the client area which the kernel can render into. 00695 Returns: - 00696 Purpose: Calculates the size of the CCamView's RendWnd. 00697 Errors: - 00698 Scope: Public 00699 SeeAlso: class CRendWnd 00700 00701 **********************************************************************************************/ 00702 00703 void CCamView::GetClientSize(int * pWidth, int * pHeight) const /* TYPENOTE: Correct */ 00704 { 00705 if (GetRenderWindow()) 00706 { 00707 WinRect wrect(0,0,0,0); 00708 GetRenderWindow()->GetClientSize(&wrect.width, &wrect.height); 00709 if (wrect.width<0) wrect.width = 0; 00710 if (wrect.height<0) wrect.height = 0; 00711 OilRect orect = wrect.ToOil(pDocView); 00712 *pWidth = orect.Width(); 00713 *pHeight = orect.Height(); 00714 } 00715 else 00716 { 00717 *pWidth = 0; 00718 *pHeight = 0; 00719 } 00720 } 00721 00722 00723 // set this to 1 to show update rectangles using cross-hatching, 0 to not 00724 #define SHOW_RECT 0 00725 00726 #if SHOW_RECT 00727 void DumpRect( wxDC *pDC, WinRect *lpRect, TCHAR *type ) 00728 { 00729 static INT32 BrushNum = wxFIRST_HATCH; 00730 wxBrush Brush; 00731 00732 Brush.SetStyle(BrushNum); 00733 Brush.SetColour(0, 0, 0); 00734 00735 if (++BrushNum > wxLAST_HATCH) 00736 BrushNum = wxFIRST_HATCH; 00737 00738 pDC->SetBrush(Brush); 00739 pDC->DrawRectangle(*lpRect); 00740 00741 if (type) 00742 { 00743 TRACE( _T("%s (%ld, %ld) [%ld, %ld]"), type, lpRect->GetLeft(), lpRect->GetTop(), 00744 lpRect->GetWidth(), lpRect->GetHeight() ); 00745 } 00746 } 00747 00748 #else 00749 #define DumpRect(pdc, rect, name) 00750 #endif 00751 00752 /********************************************************************************************* 00753 00754 > virtual void CCamView::OnDraw(CDC* pDC) 00755 00756 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00757 Created: ages ago 00758 Inputs: A pointer to the CDC object to render into. 00759 Outputs: - 00760 Returns: - 00761 Purpose: Makes sure that the kernel knows which view to render into. Retrieves the 00762 clipping rectangle from the CDC. Passes the CDC and the rectangle to 00763 DocView::OnDraw(), which does the actual rendering. 00764 Errors: - 00765 Scope: Public 00766 SeeAlso: CView::OnPrepareDC(); CCamView::OnRenderView(); DocView::OnDraw() 00767 00768 **********************************************************************************************/ 00769 00770 void CCamView::OnDraw( wxDC* pDC ) 00771 { 00772 // TRACEUSER("Gerry", _T("CCamView::OnDraw\n")); 00773 00774 if (pDocView==NULL) 00775 return; 00776 00777 // Set the current DocView, ie. the DocView being worked upon. (and the Doc!) 00778 pDocView->SetCurrent(); 00779 (pDocView->GetDoc())->SetCurrent(); 00780 00781 // Are we printing? 00782 if (CCDC::ConvertFromNativeDC(pDC)->IsPrinting()) 00783 { 00784 //TRACE( _T("BAD ! CCamView::OnDraw reckons we're printing\n")); 00785 #ifndef STANDALONE 00786 00787 // Yes - do the printing! 00788 00789 // Find out from the display context the rectangle bounding the invalid 00790 // region. 00791 WinRect clip; 00792 pDC->GetClippingBox(clip); 00793 00794 if (clip.IsEmpty()) 00795 return; 00796 00797 // Pass the drawing parameters on to the associated PrintView object. 00798 pPrintView->AttachToDC(pDC); 00799 pPrintView->OnDraw(pDC, clip.ToOil(pPrintView)); 00800 pPrintView->AttachToDC(NULL); 00801 00802 #endif 00803 } 00804 else 00805 { 00806 WinRect clip; 00807 00808 // wxWidget only provides a unified accessor, so that's 00809 // what we'll use 00810 wxRegionIterator upd( GetRenderWindow()->GetUpdateRegion() ); // get the update rect list 00811 while( upd ) 00812 { 00813 clip.x = upd.GetX(); 00814 clip.y = upd.GetY(); 00815 clip.width = upd.GetW(); 00816 clip.height = upd.GetH(); 00817 00818 // DumpRect( pDC, &clip, wxT("OnDraw UpdateRect : ") ); 00819 00820 OilRect oRect = clip.ToOil( pDocView ); 00821 // TRACEUSER("Gerry", _T("OilRect = (%d, %d) - (%d, %d)\n"), oRect.lo.x, oRect.lo.y, oRect.hi.x, oRect.hi.y); 00822 00823 pDocView->OnDraw( pDC, oRect ); 00824 00825 upd ++ ; 00826 } 00827 } 00828 00829 // TRACEUSER("Gerry", _T("Leaving CCamView::OnDraw\n")); 00830 } 00831 00832 /********************************************************************************************* 00833 00834 > afx_msg LRESULT CCamView::OnRenderView(WPARAM, LPARAM lp) 00835 00836 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00837 Created: ages ago 00838 Inputs: A pointer to a CPaintDC, cast into an LPARAM. The WPARAM is not used. 00839 Outputs: - 00840 Returns: Returns 0, indicating to Windows that the message was successfully 00841 processed. 00842 Purpose: Responds to a WM_PAINT message sent to the RendWnd window object. 00843 Effectively tricks MFC into painting the RendWnd as if it was a 00844 CView window, not a child of a CView - calls CView::OnPrepareDC() 00845 and ScreenCamView::OnDraw(). 00846 Errors: - 00847 Scope: Protected 00848 SeeAlso: class CRendWnd; CRenderWnd::OnPaint(); ScreenCamView::OnDraw(); 00849 00850 **********************************************************************************************/ 00851 00852 LRESULT CCamView::OnRenderView( WPARAM, LPARAM lp ) 00853 { 00854 PORTNOTETRACE("other","CCamView::OnRenderView - do nothing"); 00855 #ifndef EXCLUDE_FROM_XARALX 00856 wxPaintDC *pDC = (wxPaintDC *)lp; 00857 OnPrepareDC(pDC); 00858 OnDraw(pDC); 00859 #endif 00860 return 0; 00861 } 00862 00863 #define USERNAME "Mike" 00864 00865 //static RECT DriverBand; 00866 //static RECT TestBand; 00867 00868 /******************************************************************************************** 00869 00870 > void CCamView::OnFilePrint() 00871 00872 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 00873 Created: 02/09/95 00874 Purpose: The main printing control function. This is a modified version of the MFC 00875 one because MFC does not allow the concept of having a mapping between 00876 pages and physical pieces of paper other than 1 to 1. i.e. MFC can't handle 00877 two-up printing, fit lots, pamphlet printing etc. 00878 Errors: - 00879 SeeAlso: CView::OnFilePrint(); CCamView::OnFilePrintPreview() 00880 00881 ********************************************************************************************/ 00882 // WEBSTER-ranbirr-12/11/96 00883 #ifndef WEBSTER 00884 void CCamView::OnFilePrint() 00885 { 00886 #if 0 00887 #ifndef _DEBUG 00888 ::wxMessageBox(_T("Printing currently disabled in retail builds")); 00889 return; 00890 #endif 00891 #endif 00892 00893 SetCurrentStates(); 00894 00895 // Set Current states... 00896 Document* KernelDoc = GetDocument()->GetKernelDoc(); 00897 ENSURE(KernelDoc != NULL, "Oh no!!"); 00898 KernelDoc->SetCurrent(); 00899 pDocView->SetCurrent(); 00900 00901 TRACEUSER( USERNAME, _T("OnFilePrint()\n")); 00902 00903 // get default print info 00904 CCPrintInfo *pPrintInfo; 00905 pPrintInfo = new CCPrintInfo(KernelDoc,this); 00906 if (!pPrintInfo) 00907 { 00908 // Out of memory - report error and exit. 00909 Error::SetError(_R(IDS_OUT_OF_MEMORY)); 00910 InformError(); 00911 return; 00912 } 00913 00914 // Make sure the user can't get 2 print dialog boxes up 00915 PrintMonitor::SetPrintingActive(TRUE); 00916 00917 // Now bring up the print dialog 00918 if (!pPrintInfo->OnPreparePrinting()) 00919 { 00920 TRACEUSER( USERNAME, _T("OnPreparePrinting() returned FALSE\n")); 00921 delete pPrintInfo; 00922 PrintMonitor::SetPrintingActive(FALSE); 00923 return; 00924 } 00925 00926 // Get some paints out of the way 00927 ::wxSafeYield(FALSE); 00928 00929 // Ensure the current documents remain the same 00930 KernelDoc->SetCurrent(); 00931 pDocView->SetCurrent(); 00932 00933 List CompoundNodeList; 00934 NodeCompound * pCompound = NULL; 00935 NodeListItem * pItem = NULL; 00936 // Get ourselves a print view and attach it to this CCamView. 00937 // NB. Must be after the user has clicked OK on print dialog, as we set up 00938 // anti-aliasing etc. in PrintView constructor. 00939 // Delete any old print view 00940 if (pPrintView != NULL) 00941 { 00942 delete pPrintView; 00943 pPrintView = NULL; 00944 delete pPrintInfo; 00945 PrintMonitor::SetPrintingActive(FALSE); 00946 ERROR2((void)0, "OnPreparePrinting(): we already have a PrintView!"); 00947 } 00948 // make a new one 00949 pPrintView = new PrintView(pDocView->GetDoc()); 00950 if (pPrintView == NULL) 00951 { 00952 delete pPrintInfo; 00953 PrintMonitor::SetPrintingActive(FALSE); 00954 ERROR2((void)0, "Not enough memory to create PrintView object"); 00955 } 00956 // and connect it to the OilView 00957 if (!pPrintView->ConnectToOilView(this)) 00958 { 00959 delete pPrintView; 00960 pPrintView = NULL; 00961 delete pPrintInfo; 00962 PrintMonitor::SetPrintingActive(FALSE); 00963 ERROR2((void)0, "Unable to attach PrintView to CCamView."); 00964 } 00965 00966 double dpi = 96.0; 00967 00968 PrintControl* pPrCtrl = NULL; 00969 PrintComponent* pComp = (PrintComponent*)KernelDoc->GetDocComponent(CC_RUNTIME_CLASS(PrintComponent)); 00970 if (pComp != NULL) 00971 pPrCtrl = pComp->GetPrintControl(); 00972 00973 if (pPrCtrl != NULL) 00974 pPrCtrl->SetUp(KernelDoc->GetSelectedSpread()); 00975 00976 wxString strTemp; 00977 00978 TRACEUSER( "ChrisS", _T("------------------------------------------------------------------------\n")); 00979 TRACEUSER( "ChrisS", _T("------------------------------------------------------------------------\n")); 00980 TRACEUSER( "ChrisS", _T("Entering print loop\n")); 00981 TRACEUSER( "ChrisS", _T("------------------------------------------------------------------------\n")); 00982 TRACEUSER( "ChrisS", _T("------------------------------------------------------------------------\n")); 00983 00984 // ERROR3IF(pPrintInfo->m_pPD->m_pd.hDC == NULL, "NULL DC when trying to print."); 00985 // must be set (did you remember to call DoPreparePrinting?) 00986 00987 // Let's see if we can start printing... 00988 if ((!pPrintInfo->GetDC()) || 00989 !PrintMonitor::StartPrintJob(pPrintInfo->GetDC())) 00990 { 00991 TRACEUSER( USERNAME, _T("StartPrintJob() screwed up\n")); 00992 00993 // No - something went wrong. 00994 if (!pPrintInfo->GetDC()) 00995 { 00996 // No DC - set a generic "we can't print" error. 00997 Error::SetError(_R(IDE_PRINT_ERROR_SYSTEM)); 00998 } 00999 01000 // Tell user and exit. 01001 InformError(); 01002 delete pPrintInfo; 01003 PrintMonitor::SetPrintingActive(FALSE); 01004 return; 01005 } 01006 01007 // OnBeginPrinting(pPrintInfo->GetDC(), pPrintInfo); 01008 01009 // Get access to our print control object 01010 PrintControl *pPrintControl = pPrintView->GetPrintControl(); 01011 01012 Spread * pSpread = Document::GetSelectedSpread(); 01013 01014 // disable main window while printing & init printing status dialog 01015 // AfxGetMainWnd()->EnableWindow(FALSE); 01016 01017 PORTNOTE("printing", "Disable pDocInfo stuff"); 01018 #ifndef EXCLUDE_FROM_XARALX 01019 // set up document info and start the document printing process 01020 DOCINFO* pDocInfo = NULL; 01021 01022 // start document printing process 01023 if ((pPrintInfo->SetAbortProc(&dcPrint) < 0) || 01024 !pPrintInfo->SetUpDocInfo(&pDocInfo) || // SetUpDocInfo() allocs a DOCINFO for pDocInfo 01025 pDocInfo == NULL || 01026 #else 01027 if ( 01028 #endif 01029 (!pPrintInfo->GetDC()->StartDoc(wxString((TCHAR *)(Document::GetSelected()->GetTitle())))) 01030 ) 01031 { 01032 TRACEUSER( USERNAME, _T("Unable to start document\n")); 01033 01034 // enable main window before proceeding 01035 // AfxGetMainWnd()->EnableWindow(TRUE); 01036 01037 // cleanup and show error message 01038 // OnEndPrinting(&dcPrint, pPrintInfo); 01039 01040 BOOL PrintToFileUserAborted = pPrintInfo->GetPrintControl ()->GetPrintToFile (); 01041 01042 delete pPrintInfo; 01043 pPrintInfo = NULL; 01044 PrintMonitor::EndPrintJob(); 01045 01046 // Lose our PrintView 01047 delete pPrintView; 01048 pPrintView = NULL; 01049 01050 PORTNOTE("printing", "Disabled pDocInfo") 01051 #ifndef EXCLUDE_FROM_XARALX 01052 // Delete a the docinfo object 01053 if (pDocInfo != NULL) 01054 { 01055 delete pDocInfo; 01056 pDocInfo = NULL; 01057 } 01058 #endif 01059 01060 // dcPrint.Detach(); // will be cleaned up by CPrintInfo destructor 01061 if (!PrintToFileUserAborted) 01062 { 01063 InformError(_R(AFX_IDP_FAILED_TO_START_PRINT)); 01064 } 01065 PrintMonitor::SetPrintingActive(FALSE); 01066 return; 01067 } 01068 01069 BOOL StartedPrinting = FALSE; 01070 01071 // CGS: any blended compound nodes MUST be tagged as having been generated for printing 01072 NodeGroup::SetIsForPrinting (TRUE); 01073 01074 // begin page printing loop 01075 BOOL bError = TRUE; 01076 01077 // Set up the print layout system. 01078 // This allows GetNextPaper() and ReprintPaper() functions 01079 // to be called. 01080 if (!pPrintInfo->StartPrinting()) 01081 { 01082 TRACEUSER( USERNAME, _T("StartPrinting() failed\n")); 01083 // Error in starting printing. 01084 Error::SetError(_R(IDE_PRINT_ERROR_SYSTEM)); 01085 goto ExitPrint; 01086 } 01087 01088 // Must remember to tell print info object when we are done. 01089 StartedPrinting = TRUE; 01090 01091 // Work out if we should do our own PostScript 01092 BOOL DoPostScript; 01093 if ((pPrintControl->GetPrintMethod() == PRINTMETHOD_NORMAL) && 01094 (pPrintInfo->GetCCDC()->GetRenderType() == RENDERTYPE_PRINTER_PS)) 01095 { 01096 // Not printing as a bitmap and it is a PostScript printer so mark it as such. 01097 DoPostScript = TRUE; 01098 } 01099 else 01100 { 01101 // Either it's not a PostScript printer or we are printing as a bitmap, 01102 // so don't do weird PostScript stuff 01103 DoPostScript = FALSE; 01104 } 01105 01106 // If we are printing as bitmap, then set the "Printing blah.art" message in the dialog. 01107 // (This is done by RenderSimpleView() when we are printing normally). 01108 if ((pPrintControl->GetPrintMethod() != PRINTMETHOD_NORMAL) && (pPrintInfo != NULL)) 01109 // We going to print the document now 01110 pPrintInfo->SetPrinting(); 01111 01112 PORTNOTE("printing", "Disable banding call"); 01113 #ifndef EXCLUDE_FROM_XARALX 01114 // Ask the printer if it supports banding. We don't actually need the result of this call, 01115 // but asking the printer about banding has the side effect that the printer driver then 01116 // knows that we support banding! If we don't do this, then some printing (e.g. to an HP DeskJet 01117 // on Win3.1) simply chucks out blank pages, because the driver thinks we can't band, and there 01118 // isn't enough memory/disc space (or something) to do the page in one go. 01119 // 01120 // BLOCK 01121 { 01122 BOOL BandInfoSupported = FALSE; 01123 WORD wEscape = BANDINFO; 01124 if (!DoPostScript && 01125 PrintMonitor::PrintWithDriverBands && 01126 dcPrint.Escape(QUERYESCSUPPORT, sizeof(WORD), (LPCSTR) &wEscape, NULL) > 0) 01127 { 01128 // The BANDINFO Escape is supported - but we don't actually care! 01129 BandInfoSupported = TRUE; 01130 } 01131 } 01132 #endif 01133 01134 // DMc 22-7-99 01135 // MRH 11/9/00 - Major rewrite of the below david code. Fixed major logic problem and 01136 // cut out the regeneratenodes function as this is not required! 01137 BevelTools::GetAllNodesUnderNode(pSpread, &CompoundNodeList, CC_RUNTIME_CLASS(NodeCompound)); 01138 01139 dpi = OSRenderRegion::GetFixedDCPPI(*pPrintInfo->GetDC()).GetWidth(); 01140 01141 if (pPrintControl) 01142 dpi = (double)pPrintControl->GetDotsPerInch(); 01143 01144 pItem = (NodeListItem *)CompoundNodeList.GetHead(); 01145 01146 while (pItem) 01147 { 01148 pCompound = (NodeCompound *)pItem->pNode; 01149 01150 if (pCompound) 01151 { 01152 if (pCompound->RegenerateForPrinting()) 01153 { 01154 pCompound->SetDPI(dpi); 01155 pCompound->SetPrinting(TRUE); 01156 } 01157 } 01158 01159 pItem = (NodeListItem *)CompoundNodeList.GetNext(pItem); 01160 } 01161 01162 TRACEUSER( "DavidM", _T("Beginning print dpi %d\n"), dpi); 01163 01164 // Loop around for each physical page ("paper") we have to print. Note that now we may print out 01165 // multiple physical pieces of paper for each "paper" (page) as we may do C, M, Y, K plates etc. 01166 01167 while (pPrintInfo->MorePaper()) 01168 { 01169 // Start off the print marks system bits for this paper 01170 // We lock progress window updates during this call so that the progress window will 01171 // ignore all attempts to update the display. 01172 pPrintInfo->LockProgressUpdate(TRUE); 01173 EnumeratePagePatches(pPrintInfo); 01174 pPrintInfo->LockProgressUpdate(FALSE); 01175 01176 // Initialise the plate printing system for any plates of this page 01177 // It also sets up GetNextPlate() and ReprintPlate functions 01178 UINT32 plateerr; 01179 if (!pPrintInfo->StartPlatePrinting(pPrintView, &plateerr)) 01180 { 01181 TRACEUSER( USERNAME, _T("StartPlatePrinting() failed\n")); 01182 // Error in startplateprinting! the error id may have been returned 01183 // We ignore the id if zero, ie StartPlatePrinting reported it. 01184 if (plateerr>0) 01185 { 01186 String_64 reason; 01187 String_256 ErrorMsg; 01188 BOOL ok = ( reason.Load(plateerr) ); 01189 ok = ok && ( ErrorMsg.MakeMsg( _R(IDE_PRINT_ERROR), (LPCTSTR) reason) > 0); 01190 if (ok) 01191 Error::SetError(_R(IDE_PRINT_ERROR), (TCHAR *) ErrorMsg, 0); 01192 else 01193 Error::SetError(_R(IDE_PRINT_USERABORT)); 01194 } 01195 goto ExitPrint; 01196 } 01197 01198 // Loop around for each logical plate we have to print - this generates a piece of physical 01199 // paper out of the printer on each pass. 01200 while (pPrintInfo->MorePlates()) 01201 { 01202 // Get the first "paper" (plate or page) to print 01203 pPrintInfo->GetNextPaper(); 01204 01205 // and set up the plate printing system ready to print the next plate on the next pass 01206 if (!pPrintInfo->SetNextPlate(pPrintView)) 01207 { 01208 TRACEUSER( USERNAME, _T("SetNextPlate() failed!\n")); 01209 // Error in starting printing. 01210 Error::SetError(_R(IDE_PRINT_ERROR_SYSTEM)); 01211 pPrintInfo->EndPlatePrinting(pPrintView); 01212 goto ExitPrint; 01213 } 01214 01215 // Now, prepare this paper (plate/page) for printing 01216 TRACEUSER( USERNAME, _T("Starting physical page\n")); 01217 // OnPrepareDC(pPrintInfo->GetDC(), pPrintInfo); 01218 01219 // check for end of print 01220 if (!pPrintInfo->m_bContinuePrinting || pPrintInfo->Abort()) 01221 { 01222 TRACEUSER( USERNAME, _T("Print abort 1\n")); 01223 pPrintInfo->EndPlatePrinting(pPrintView); 01224 goto ExitPrint; 01225 } 01226 01227 // attempt to start the current paper 01228 pPrintInfo->GetDC()->StartPage(); 01229 if (0) // error handling non-existant 01230 { 01231 TRACEUSER( USERNAME, _T("Unable to StartPage()\n")); 01232 Error::SetError(_R(IDE_PRINT_ERROR_SYSTEM)); 01233 pPrintInfo->EndPlatePrinting(pPrintView); 01234 goto ExitPrint; 01235 } 01236 01237 // Is it a PostScript printer? 01238 if (DoPostScript) 01239 { 01240 // Yes, so before we start the page, we send our PostScript procset to the device. 01241 if (!PrintPSRenderRegion::InitPSDevice(pPrintInfo->GetDC(), pPrintView)) 01242 { 01243 TRACEUSER( USERNAME, _T("Unable to Init PS device\n")); 01244 Error::SetError(_R(IDE_PRINT_ERROR_SYSTEM)); 01245 pPrintInfo->EndPlatePrinting(pPrintView); 01246 goto ExitPrint; 01247 } 01248 } 01249 01250 PORTNOTE("printing", "Disable banding call"); 01251 #ifndef EXCLUDE_FROM_XARALX 01252 // If banding, find the first band to print 01253 // Only use driver banding if the preference says so, and never band 01254 // to PS devices (yes, the Win95 PS driver supports banding, except 01255 // not really and it just screws up). 01256 if (PrintMonitor::PrintWithDriverBands && !DoPostScript) 01257 { 01258 // Do the driver banding 01259 dcPrint.Escape(NEXTBAND, 0, NULL, (LPSTR) &DriverBand); 01260 01261 TRACEUSER( USERNAME, _T("INITIALBAND: (%d,%d), (%d, %d)\n"), 01262 DriverBand.left, DriverBand.top, DriverBand.right, DriverBand.bottom); 01263 } 01264 #endif 01265 01266 TRACEUSER( USERNAME, _T("Starting PrintPaper() loop...\n")); 01267 01268 // Now render the paper into each band. 01269 BOOL MoreBands = TRUE; 01270 while (MoreBands) 01271 { 01272 TRACEUSER( USERNAME, _T("Calling PrintPaper()...\n")); 01273 // Print this piece of paper (to the current band) 01274 if (!PrintPaper(pPrintInfo->GetDC(), pPrintInfo, pPrintControl)) 01275 { 01276 // Something went wrong - quit and abort print job. 01277 TRACEUSER( USERNAME, _T("PrintPaper() failed\n")); 01278 Error::SetError(_R(IDE_PRINT_ERROR_SYSTEM)); 01279 pPrintInfo->EndPlatePrinting(pPrintView); 01280 goto ExitPrint; 01281 } 01282 01283 // Only use driver banding if the preference says so, and never band to PS devices. 01284 MoreBands = FALSE; // Assume no more bands until told otherwise 01285 PORTNOTE("printing", "Disable banding call"); 01286 #ifndef EXCLUDE_FROM_XARALX 01287 if (PrintMonitor::PrintWithDriverBands && !DoPostScript) 01288 { 01289 // We've printed this band - see if printer driver has any bands left, 01290 // NB we kludge this as some drivers keep returning the same band...fabby eh? 01291 dcPrint.Escape(NEXTBAND, 0, NULL, (LPSTR) &DriverBand); 01292 TRACEUSER( USERNAME, _T("Driver returned valid band: (%d,%d), (%d, %d)\n"), 01293 DriverBand.left, DriverBand.top, DriverBand.right, DriverBand.bottom); 01294 01295 // If it does, then we need to loop around to print this physical piece of paper 01296 // into the next band... 01297 if (!IsRectEmpty(&DriverBand)) 01298 { 01299 TRACEUSER( USERNAME, _T("Forcing a reprint of paper [for band: (%d,%d), (%d, %d)]\n"), 01300 DriverBand.left, DriverBand.top, DriverBand.right, DriverBand.bottom); 01301 MoreBands = TRUE; 01302 } 01303 else 01304 { 01305 TRACEUSER( USERNAME, _T("End of bands for this page\n")); 01306 } 01307 } 01308 #endif 01309 01310 // If we're going to print more bands, then set up the "paper" for the next band 01311 if (MoreBands) 01312 { 01313 // Tell the print control that we want the same "paper" again, rather than moving 01314 // on to the next one. 01315 pPrintControl->ReprintPaper(); 01316 01317 // And reset all the PrintInfo data for this "paper" ready for the next band 01318 pPrintInfo->GetNextPaper(); 01319 } 01320 } 01321 01322 TRACEUSER( USERNAME, _T("Ending physical page\n")); 01323 01324 // End of page clean up. 01325 // Note that we don't check for an error from EndPage() because due to 01326 // a bug (in Windows/GDI) it returns -1 when using banding. 01327 // The MS workaround is to not check the return value! 01328 pPrintInfo->GetDC()->EndPage(); 01329 01330 if (!pPrintInfo->m_bContinuePrinting || pPrintInfo->Abort()) 01331 { 01332 TRACEUSER( USERNAME, _T("Print abort 2\n")); 01333 pPrintInfo->EndPlatePrinting(pPrintView); 01334 goto ExitPrint; 01335 } 01336 01337 // Any more plates to print?, if so we need to print the plate as a complete new page. 01338 // We set ReprintPaper so that the next pass tries to print the same "paper" (document page) 01339 // again, but we've moved it on to the next plate (in SetNextPlate, above), so we'll actually 01340 // be rendering a different plate the next time around. 01341 if (pPrintInfo->MorePlates()) 01342 pPrintControl->ReprintPaper(); 01343 } 01344 01345 // End the plate printing function 01346 pPrintInfo->EndPlatePrinting(pPrintView); 01347 } 01348 01349 // Set the flag to indicate that we're exiting happily 01350 bError = FALSE; 01351 01352 01353 ExitPrint: 01354 if (!bError) 01355 pPrintInfo->GetDC()->EndDoc(); 01356 else 01357 { 01358 TRACEUSER( USERNAME, _T("ExitPrint: an error occured()\n")); 01359 // An error occured - abort the job. 01360 // pPrintInfo->GetDC()->AbortDoc(); 01361 01362 // If the user did not cancel the job, report what went wrong. 01363 if (!pPrintInfo->Abort()) 01364 InformError(); 01365 } 01366 01367 // cleanup document printing process 01368 PrintMonitor::EndPrintJob(); 01369 01370 // AfxGetMainWnd()->EnableWindow(); // enable main window 01371 01372 // OnEndPrinting(pPrintInfo->GetDC(), pPrintInfo); // clean up after printing 01373 01374 // Clean up kernel printing code 01375 if (StartedPrinting) 01376 pPrintInfo->EndPrinting(); 01377 01378 PORTNOTE("printing", "Remove DOCINFO stuff"); 01379 #ifndef EXCLUDE_FROM_XARALX 01380 // Delete a the docinfo object 01381 if (pDocInfo != NULL) 01382 { 01383 delete pDocInfo; 01384 pDocInfo = NULL; 01385 } 01386 #endif 01387 01388 PrintMonitor::SetPrintingActive(FALSE); 01389 01390 // Lose our PrintView (if it exists) - not needed anymore. 01391 if (pPrintView) 01392 { 01393 delete pPrintView; 01394 pPrintView = NULL; 01395 } 01396 01397 // Deleting the print view appears to unset the current document, so fix it 01398 KernelDoc->SetCurrent(); 01399 pDocView->SetCurrent(); 01400 01401 if (pPrintInfo) 01402 { 01403 delete pPrintInfo; 01404 pPrintInfo = NULL; 01405 } 01406 01407 // If we need to redraw everything then do it. 01408 if (PrintMonitor::FullRedrawNeeded) 01409 { 01410 // iterate through all the documents and get them to redraw themselves 01411 Document* pDoc = (Document*) Camelot.Documents.GetHead(); 01412 01413 while (pDoc!=NULL) 01414 { 01415 // Get it to redraw itself 01416 pDoc->ForceRedraw(); 01417 01418 // get the next document in the list 01419 pDoc = (Document*) Camelot.Documents.GetNext(pDoc); 01420 } 01421 } 01422 01423 // mark the PrintMonitor as not needing a redraw 01424 PrintMonitor::WantFullRedraw(FALSE); 01425 01426 // DMc restore the compound nodes dpi's 01427 pItem = (NodeListItem *)CompoundNodeList.GetHead(); 01428 01429 while (pItem) 01430 { 01431 pCompound = (NodeCompound *)pItem->pNode; 01432 01433 if (pCompound) 01434 { 01435 if (pCompound->RegenerateForPrinting()) 01436 { 01437 pCompound->SetDPI(96.0); 01438 pCompound->SetPrinting(FALSE); 01439 01440 pCompound->RegenerateNode(NULL, FALSE); 01441 } 01442 } 01443 01444 pItem = (NodeListItem *)CompoundNodeList.GetNext(pItem); 01445 } 01446 01447 CompoundNodeList.DeleteAll(); 01448 01449 NodeGroup::KillAllBlendBecomeAConsLists (FALSE, TRUE); 01450 NodeGroup::SetIsForPrinting (FALSE); 01451 01452 TRACEUSER( "ChrisS", _T("------------------------------------------------------------------------\n")); 01453 TRACEUSER( "ChrisS", _T("------------------------------------------------------------------------\n")); 01454 TRACEUSER( "ChrisS", _T("Exiting print loop\n")); 01455 TRACEUSER( "ChrisS", _T("------------------------------------------------------------------------\n")); 01456 TRACEUSER( "ChrisS", _T("------------------------------------------------------------------------\n")); 01457 } 01458 01459 #endif //webster 01460 01461 01462 01463 // Size of bands to use when printing as bitmap. 01464 #define BAND_HEIGHT (128) 01465 01466 /******************************************************************************************** 01467 01468 > BOOL ScreenCamView::PrintPaper(CDC *pPrintDC, 01469 CCPrintInfo *pPrintInfo, 01470 PrintControl *pPrintControl) 01471 01472 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 01473 Created: 05/11/95 01474 Inputs: pPrintDC - the (printer) device context to print to. 01475 pPrintInfo - the object to use for layout control. 01476 Returns: TRUE if the paper was printed ok; 01477 FALSE if not. 01478 Purpose: Prints all the ink onto a physical piece of paper. This includes coping 01479 with patches (multiple copies on one piece of paper, and banding bitmap 01480 printing to improve performance. 01481 Errors: pPrintDC has a bad DC handle => ERROR3 01482 Problem with setting up clipping region => ERROR2 01483 SeeAlso: ScreenCamView::OnFilePrint; ScreenCamView::GetPrintClipRect 01484 01485 ********************************************************************************************/ 01486 // WEBSTER-ranbirr-12/11/96 01487 #ifndef WEBSTER 01488 BOOL CCamView::PrintPaper(CNativeDC *pPrintDC, 01489 CCPrintInfo *pPrintInfo, 01490 PrintControl *pPrintControl) 01491 { 01492 // TRACEUSER( "Tim", _T("PrintPaper() started\n")); 01493 01494 // TRACEUSER( "Tim", _T("PrintPaper() printing band=(%d,%d),(%d,%d)\n"), 01495 // DriverBand.left, DriverBand.top, DriverBand.right, DriverBand.bottom); 01496 01497 01498 // Page successfully started, so now render the page by doing each 'patch' 01499 // in turn. Note that we store the patch information in the print view, 01500 // which the view will use when setting up to render 01501 // (see PrintView::ConstructRenderingMatrix()) 01502 while (pPrintInfo->GetNextPatch(&pPrintView->PatchInfo)) 01503 { 01504 // Tell the view what scale this is. 01505 pPrintView->SetViewScale(pPrintView->PatchInfo.Scale / FIXED16(100)); 01506 01507 // Set up drawing rect to entire page (in logical coordinates) 01508 wxRect r(wxPoint(0, 0), pPrintDC->GetSize()); 01509 wxCoord x1=pPrintDC->DeviceToLogicalX(r.GetLeft()); 01510 wxCoord x2=pPrintDC->DeviceToLogicalX(r.GetRight()+1); 01511 wxCoord y1=pPrintDC->DeviceToLogicalY(r.GetTop()); 01512 wxCoord y2=pPrintDC->DeviceToLogicalY(r.GetBottom()+1); 01513 wxCoord lowx=wxMin(x1,x2); 01514 wxCoord highx=wxMax(x1,x2); 01515 wxCoord lowy=wxMin(y1,y2); 01516 wxCoord highy=wxMax(y1,y2); 01517 pPrintInfo->m_rectDraw=wxRect(wxPoint(lowx,lowy),wxSize(highx-lowx,highy-lowy)); 01518 01519 // Let's band this to make performance acceptable. 01520 01521 // Bodge banding - many printer drivers don't do banding so performance 01522 // is a dog (i.e. not enough memory to print on my 32Mb machine!) 01523 const INT32 BandHeight = BAND_HEIGHT; 01524 INT32 BottomOfPage = pPrintInfo->m_rectDraw.GetBottom()+1; //+1 is wxRect stupidity 01525 // const INT32 PageHeight = pPrintInfo->m_rectDraw.GetBottom() - pPrintInfo->m_rectDraw.GetTop(); 01526 01527 // Find print control object for this document, to see if we are 01528 // printing via bitmap, and so if we need to band the output. 01529 PrintMethodType PrintType; 01530 PrintType = pPrintControl->GetPrintMethod(); 01531 01532 // Work out whether or not to use banding for printing. 01533 // (i.e. are we printing with a bitmap?) 01534 if ((PrintType == PRINTMETHOD_AABITMAP) || 01535 (PrintType == PRINTMETHOD_BITMAP)) 01536 { 01537 // Banding is required - set up first band. 01538 pPrintInfo->SetSliderSubRangeMax(pPrintInfo->m_rectDraw.GetHeight() / BAND_HEIGHT); 01539 pPrintInfo->m_rectDraw.height = BandHeight; 01540 } 01541 01542 INT32 CurrentBand = 0; 01543 01544 TRACEUSER( "Tim", _T("Rectangle: (%d,%d), (%d,%d) BottomOfPage=%d\n"), 01545 pPrintInfo->m_rectDraw.GetLeft(), pPrintInfo->m_rectDraw.GetTop(), 01546 pPrintInfo->m_rectDraw.GetRight()+1,pPrintInfo->m_rectDraw.GetBottom()+1, 01547 BottomOfPage); 01548 01549 while (pPrintInfo->m_rectDraw.GetBottom()+1 <= BottomOfPage) 01550 { 01551 // Update slider 01552 if ((PrintType == PRINTMETHOD_AABITMAP) || 01553 (PrintType == PRINTMETHOD_BITMAP)) 01554 { 01555 // Doing our own banding, so update progress slider. 01556 pPrintInfo->SetSliderSubRangePos(CurrentBand); 01557 } 01558 01559 // 01560 // Strange stuff to work out what area to print in this band. 01561 // 01562 WinRect OILClip = GetPrintClipRect(pPrintDC, pPrintInfo); 01563 01564 // Check for no intersection. 01565 if (!OILClip.IsEmpty()) 01566 { 01567 // Put this clip region into print info structure. 01568 pPrintInfo->m_rectDraw = OILClip; 01569 01570 wxRect oldclip(wxPoint(0,0), wxSize(0,0)); 01571 pPrintDC->GetClippingBox(oldclip); 01572 pPrintDC->SetClippingRegion(pPrintInfo->m_rectDraw); 01573 01574 // Print the band. 01575 pPrintView->SetCurrent(); 01576 OnPrint(pPrintDC, pPrintInfo); 01577 01578 pPrintDC->SetClippingRegion(oldclip); 01579 01580 if (!pPrintInfo->m_bContinuePrinting || pPrintInfo->Abort()) 01581 // Printing has finished. 01582 return FALSE; 01583 } 01584 01585 // Is this the last band? 01586 if (pPrintInfo->m_rectDraw.GetBottom()+1 < BottomOfPage) 01587 { 01588 // No - get the next band. 01589 pPrintInfo->m_rectDraw.y = pPrintInfo->m_rectDraw.GetBottom()+1; 01590 pPrintInfo->m_rectDraw.height = BandHeight; 01591 01592 // Limit to bottom of page if necessary. 01593 if (pPrintInfo->m_rectDraw.GetBottom()+1 > BottomOfPage) 01594 pPrintInfo->m_rectDraw.height -= pPrintInfo->m_rectDraw.GetBottom()+1 - BottomOfPage; 01595 } 01596 else 01597 { 01598 // No bands left - so we're done here. 01599 TRACEUSER( "Tim", _T("No bespoke banding\n")); 01600 break; 01601 } 01602 01603 CurrentBand++; 01604 } 01605 } 01606 01607 TRACEUSER( "Tim", _T("PrintPaper() finished\n")); 01608 01609 // All worked ok 01610 return TRUE; 01611 } 01612 #endif //webster 01613 01614 01615 /******************************************************************************************** 01616 01617 > WinRect CCamView::GetPrintClipRect(CDC *pPrintDC, CCPrintInfo *pPrintInfo) 01618 01619 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 01620 Created: 05/11/95 01621 Inputs: pPrintDC - the device context we are printing to - we need this because 01622 otherwise the PrintView object can't compute the rendering 01623 matrix, which we need in order to find out the position of the 01624 patch on the DC. 01625 pPrintInfo - the print info object, which specifies the window onto the 01626 page/DC that we can print into. 01627 Returns: The intersection of the area of the current patch (as held in 01628 ScreenCamView::pPrintView->PatchInfo) and the printable area of the DC, 01629 in WinCoords. 01630 Purpose: Works out which area of the paper to print on, given the current patch 01631 (as held in the PrintView object), and the printing area specified by 01632 the CCPrintInfo object. 01633 SeeAlso: ScreenCamView::PrintPaper; PrintView::ConstructRenderingMatrix 01634 01635 ********************************************************************************************/ 01636 // WEBSTER-ranbirr-12/11/96 01637 #ifndef WEBSTER 01638 WinRect CCamView::GetPrintClipRect(CNativeDC *pPrintDC, CCPrintInfo *pPrintInfo) 01639 { 01640 // We need to attach the PrintView while we are doing this so it knows how big 01641 // the pixels are and so on. 01642 pPrintView->AttachToDC(pPrintDC); 01643 01644 // Get the rendering matrix for this patch 01645 Spread *pSpread = Document::GetSelectedSpread(); // Should be PatchInfo.pSpread 01646 Matrix TheMatrix = pPrintView->ConstructRenderingMatrix(pSpread); 01647 01648 // Use matrix to transform clip rect of patch to Oil coords. 01649 DocRect ClipRect = pPrintView->PatchInfo.GetClipRect(FALSE,FALSE); 01650 01651 // turn this clip rect into an OilRect 01652 OilRect PatchClipRect(OilCoord(ClipRect.lo.x, ClipRect.lo.y), 01653 OilCoord(ClipRect.hi.x, ClipRect.hi.y)); 01654 01655 TheMatrix.transform(&PatchClipRect.lo); 01656 TheMatrix.transform(&PatchClipRect.hi); 01657 01658 // Rendering transform may involve a rotation so correct if necesary. 01659 pPrintView->CorrectRotatedRectangle((Rect *) &PatchClipRect); 01660 01661 // We need to inflate the clipping rectangle as this is used to determin the 01662 // bitmap size when rendering to AABITMAP output (and BITMAP). 01663 // Ok, There is a problem here.... We need to set the clip rectangle to cover 01664 // the crop area too. Otherwise, when rendering text as text, GDI will bin the 01665 // crop mark text we render. We do this after the transform to avoid the transform 01666 // scaling this unscalable value. 01667 pPrintView->PatchInfo.InflateRectBy(&PatchClipRect, TRUE, TRUE); 01668 01669 // Convert the OIL cliprect to logical GDI units 01670 WinRect WinClipRect; 01671 WinClipRect = PatchClipRect.ToWin(pPrintView); 01672 01673 // Find intersection with clip rect. 01674 WinRect OILClip=WinClipRect; 01675 OILClip.Intersect(pPrintInfo->m_rectDraw); 01676 01677 // Finished messing with the PrintView for the mo so we can detach the DC. 01678 // It is eventually re-attached (in ScreenCamView::OnDraw()) when we call OnPrint(). 01679 pPrintView->AttachToDC(NULL); 01680 01681 return OILClip; 01682 } 01683 #endif //webster 01684 01685 /******************************************************************************************** 01686 01687 > void CCamView::EnumeratePagePatches(CCPrintInfo *pPrintInfo) 01688 01689 Author: Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com> 01690 Created: 14/09/96 01691 Inputs: pPrintInfo - the print info object, which specifies the window onto the 01692 page/DC that we can print into. 01693 Returns: 01694 Purpose: In order to locate crop marks / registration marks etc correctly, we need 01695 to work out the bounds of all patches printed on a single sheet of paper. 01696 This routine does just that. 01697 01698 ********************************************************************************************/ 01699 // WEBSTER-ranbirr-12/11/96 01700 #ifndef WEBSTER 01701 void CCamView::EnumeratePagePatches(CCPrintInfo *pPrintInfo) 01702 { 01703 #ifndef EXCLUDE_FROM_RALPH 01704 #ifndef STANDALONE 01705 01706 DocRect Bounds; 01707 DocRect cliprect; 01708 INT32 bleed=0; 01709 BOOL emuldwn=FALSE; 01710 01711 // get a pointer to the print marks manager 01712 PrintMarksMan *pMarksMan = GetApplication()->GetMarksManager(); 01713 if (pMarksMan==NULL) 01714 return; 01715 01716 // Destroy what we may already have from a previous piece of paper 01717 pMarksMan->ResetPageRects(); 01718 01719 PrintPatchInfo* pPatchInfo = &pPrintView->PatchInfo; 01720 if (pPrintInfo->GetNextPaper()) 01721 { 01722 // scan through each patch on the first paper region 01723 while (pPrintInfo->GetNextPatch(pPatchInfo)) 01724 { 01725 // Get raw patch clip rectangle 01726 cliprect = pPatchInfo->GetClipRect(FALSE,FALSE); 01727 bleed = pPatchInfo->GetBleed(); 01728 emuldwn = pPatchInfo->EmulsionDown; 01729 // dont inflate by the bleed, this is passed in and used by the print marks manager 01730 //cliprect.Inflate(pPatchInfo->Bleed); 01731 // Build a Spread=>OS conversion matrix for this patch 01732 Matrix TheMatrix = pPrintView->ConstructRenderingMatrix(pPatchInfo->pSpread); 01733 // transform the patch 01734 TheMatrix.transform(&cliprect.lo); 01735 TheMatrix.transform(&cliprect.hi); 01736 // Rendering matrix may involve a rotation when printing so correct the rectangle 01737 // for this if necessary. 01738 pPrintView->CorrectRotatedRectangle((Rect *)&cliprect); 01739 // tell the marks manager about these bounds. 01740 pMarksMan->AddPageRect(cliprect); 01741 } 01742 } 01743 01744 // Get the marks manager to update its imagesetting rect 01745 pMarksMan->SetImagesettingRect(); 01746 pMarksMan->SetBleed(bleed); 01747 pMarksMan->SetEmulsionDown(emuldwn); 01748 01749 // reprint this piece of paper so we dont upset the print system 01750 pPrintInfo->ReprintPaper(); 01751 01752 #endif 01753 #endif 01754 } 01755 01756 #endif //webster 01757 01758 PORTNOTE("printing", "Disabled lots of printing code") 01759 #ifndef EXCLUDE_FROM_XARALX 01760 01761 /********************************************************************************************* 01762 > BOOL CCamView::OnPreparePrinting(CPrintInfo* pInfo) 01763 01764 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 01765 Created: by the wonderful AppWizard 01766 Inputs: - 01767 Outputs: Fills the passed CPrintInfo with some stuff. 01768 Returns: TRUE if successful preparation for printing. 01769 Purpose: Current just returns that value of CView::DoPreparePrinting() 01770 Errors: - 01771 Scope: Public 01772 SeeAlso: CView::DoPreparePrinting() 01773 01774 **********************************************************************************************/ 01775 01776 BOOL CCamView::OnPreparePrinting(CPrintInfo* pInfo) 01777 { 01778 #ifndef STANDALONE 01779 01780 // if (!CCPrintDialog::OnPreparePrinting(pInfo,pDocView->GetDoc())) 01781 // ERROR2(FALSE,"Unable to initialise the customized print dialog"); 01782 01783 // default preparation 01784 BOOL Result = CCamView::DoPreparePrinting(pInfo); 01785 if (!Result) 01786 return FALSE; 01787 01788 // Check because brainless CView only checks for valid DC in debug builds - handy eh? NOT! 01789 if (pInfo->m_pPD->m_pd.hDC == NULL) 01790 { 01791 ERROR1(FALSE,_R(IDE_NULL_PRINTDC)); 01792 //ERROR2(FALSE, "No valid DC returned by print dialog!"); 01793 } 01794 01795 // Get ourselves a print view and attach it to this CCamView. 01796 // NB. Must be after the user has clicked OK on print dialog, as we set up 01797 // anti-aliasing etc. in PrintView constructor. 01798 if (pPrintView != NULL) 01799 { 01800 delete pPrintView; 01801 pPrintView = NULL; 01802 ERROR2(FALSE, "OnPreparePrinting(): we already have a PrintView!"); 01803 } 01804 01805 pPrintView = new PrintView(pDocView->GetDoc()); 01806 if (pPrintView == NULL) 01807 ERROR2(FALSE, "Not enough memory to create PrintView object"); 01808 01809 if (!pPrintView->ConnectToOilView(this)) 01810 { 01811 delete pPrintView; 01812 pPrintView = NULL; 01813 ERROR2(FALSE, "Unable to attach PrintView to CCamView."); 01814 } 01815 01816 #endif 01817 01818 // OK if we got this far. 01819 return TRUE; 01820 } 01821 01822 #endif //EXCLUDE_FROM_XARALX 01823 01825 // Menu functions 01826 01827 01828 01829 /********************************************************************************************* 01830 > void CCamView::OnFilePrintPreview() 01831 01832 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 01833 Created: ages ago 01834 Inputs: - 01835 Outputs: - 01836 Returns: - 01837 Purpose: Simply makes CView::OnFilePrintPreview() have public scope. 01838 Used by the menu system. 01839 Errors: - 01840 Scope: Public 01841 SeeAlso: CView::OnFilePrintPreview(); CCamView::OnFilePrint() 01842 01843 **********************************************************************************************/ 01844 01845 void CCamView::OnFilePrintPreview() 01846 { 01847 SetCurrentStates(); 01848 01849 // CView::OnFilePrintPreview(); 01850 } 01851 01852 01853 /********************************************************************************************* 01854 > void CCamView::InvalidateView(const OilRect* pRect = NULL, BOOL updatenow = FALSE) 01855 01856 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 01857 Created: ages ago 01858 Inputs: A pointer to the client area rectangle, an OilRect, which is to be 01859 invalidated (marked as needing to be redrawn). This parameter may be 01860 omitted. If the first parameter is present, an optional second parameter 01861 may be specified, which if TRUE tells Windows to immediately send a 01862 WM_PAINT message to the view, which will force an instant redraw of any 01863 invalid areas (normally Windows waits until all other messages have been 01864 processed before sending the WM_PAINT message). 01865 Outputs: - 01866 Returns: - 01867 Purpose: Invalidates the appropriate section of the RendWnd client area - if the 01868 passed parameter is NULL then the whole client area is invalidated. The 01869 rectangle will be redrawn at some time in the (near) future. 01870 Errors: - 01871 Scope: Public 01872 SeeAlso: class CRendWnd; CCamView::OnDraw() 01873 01874 **********************************************************************************************/ 01875 01876 void CCamView::InvalidateView(const OilRect* pRect, BOOL updatenow) 01877 { 01878 if (pRect != NULL) 01879 { 01880 // Convert passed rectangle to an MFC-derived type and invalidate it. Add an extra 01881 // pixel to the right and bottom edges of the rectangle to ensure that the whole 01882 // rectangle, after scaling and rounding, is invalidated. 01883 WinRect r = pRect->ToWin( pDocView ); 01884 // r.width++; 01885 // r.height++; 01886 GetRenderWindow()->Refresh( true, &r ); 01887 } 01888 else 01889 { 01890 // We are completely redrawing the client area, so it is possible that the 01891 // "cached" previous scroll offsets, contained in OldOffset, will become 01892 // incorrect. 01893 GetRenderWindow()->Refresh( true ); 01894 GetScrollOffset(&OldOffset); 01895 } 01896 01897 if (updatenow) GetRenderWindow()->Update(); 01898 } 01899 01900 01901 /********************************************************************************************* 01902 > BOOL CCamView::StartDrag(Operation* pOp, DragType type, BOOL KeepAccuracy) 01903 01904 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 01905 Created: ages ago 01906 Inputs: A pointer to the current (drag) Operation; the type of the drag. 01907 Outputs: - 01908 Returns: Returns TRUE if successful. Returns FALSE if a timer couldn't be allocated. 01909 Purpose: Begins a drag operation, from the point of view of the OIL layer. Unbounds 01910 the mouse cursor, so it can go off-screen (display driver permitting). 01911 Captures all mouse input, to guarantee that the drag being started will 01912 terminate properly at some time in the future. Sets some internal variables 01913 indicating that ScreenView is in "drag mode". Finally, asks the system for a 01914 timer which is used to generate "idle" mouse events. 01915 Errors: ASSERTion failure if the ScreenView is already dragging. 01916 Scope: Public 01917 SeeAlso: CCamView::EndDrag(); CCamView::HandleDragEvent(); 01918 01919 **********************************************************************************************/ 01920 01921 BOOL CCamView::StartDrag(Operation* pOp, DragType type, BOOL KeepAccuracy) 01922 { 01923 ENSURE( pCurrentDragOp == 0, "CCamView::StartDrag: pCurrentDragOp is not zero"); 01924 01925 // This has been commented out as some screen drivers can not handle the mouse drifting 01926 // off the top of the screen. 01927 // Unbound mouse from the screen and set the current drag operation. Note that under 01928 // Win32 raw mouse coordinates change from being 16-bit INTs to 16-bit SHORTs. 01929 //WinRect unbound(SHRT_MIN / 4, SHRT_MIN / 4, SHRT_MAX / 4, SHRT_MAX / 4); 01930 //::GetClipCursor(&MouseClipRect); 01931 //::ClipCursor(&unbound); 01932 GetRenderWindow()->CaptureMouse(); 01933 01934 // Remember what kind of drag we are performing. 01935 pCurrentDragOp = pOp; 01936 CurrentDragType = type; 01937 OLERecaptureMouse = FALSE; 01938 DragKeepAccuracy = KeepAccuracy; 01939 AutoScrollExcludeRulers = FALSE; 01940 m_OLELastOutTime.Sample(); 01941 return TRUE; 01942 } 01943 01944 01945 01946 /********************************************************************************************* 01947 > BOOL CCamView::EndDrag(Operation* pOp) 01948 01949 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 01950 Created: ages ago 01951 Inputs: A pointer to the current drag operation (currently not used). 01952 Outputs: - 01953 Returns: TRUE if the drag is successfully terminated. 01954 Purpose: Finishes a drag operation in the OIL layer. Releases mouse capture and 01955 restores the previous mouse cursor clipping rectangle (generally the screen). 01956 Sets internal variables to indicate that ScreenView is not in "drag mode". 01957 Kills the timer set in StartDrag(). 01958 Errors: ASSERTion failure if ScreenView was not already in "drag mode". 01959 Scope: Public 01960 SeeAlso: CCamView::StartDrag(); CCamView::HandleDragEvent() 01961 01962 **********************************************************************************************/ 01963 01964 BOOL CCamView::EndDrag(Operation*) 01965 { 01966 /* 01967 #ifdef _DEBUG 01968 // Prevent a very nasty recursive ENSURE! 01969 if (!CCamApp::IsDisabled()) 01970 { 01971 ENSURE(pCurrentDragOp != 0, "CCamView::EndDrag: pCurrentDragOp is zero"); 01972 } 01973 #endif // _DEBUG 01974 */ 01975 // Restore the previous mouse clipping rectangle. Windows will move the 01976 // mouse, if necessary, so that the mouse is within the new clipping 01977 // rectangle (or so the documentation says!) 01978 //::ClipCursor(&MouseClipRect); 01979 pCurrentDragOp = 0; 01980 FirstClickButton = 0; 01981 DragKeepAccuracy = TRUE; 01982 if (GetRenderWindow()->GetCapture() == RenderWindow) 01983 GetRenderWindow()->ReleaseMouse(); 01984 01985 // Check status of temporary tool selection - this is because we don't change tool 01986 // mid-drag! (e.g. user holds down Alt to get selector, starts drag, releases Alt, 01987 // then ends drag - we want to restore the original tool). 01988 Tool::EndDrag(); 01989 01990 // Kill the timer started in HandleDragEvent(). 01991 m_DragIdleTimer.Stop(); 01992 01993 return TRUE; 01994 } 01995 01996 /******************************************************************************************** 01997 > BOOL CCamView::GetCurrentMousePos(OilCoord* pMousePos) const 01998 01999 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 02000 Created: 12/10/94 02001 Inputs: - 02002 Outputs: pMousePos the mouse position within this view, in OIL coordinates 02003 Returns: TRUE if the mouse is within this view, and hence that *pMousePos holds 02004 its position; FALSE if the mouse is outside the view (in which case 02005 *pMousePos is unchanged). 02006 Purpose: Finds out the current mouse position within this view window. 02007 Errors: - 02008 SeeAlso: - 02009 ********************************************************************************************/ 02010 02011 BOOL CCamView::GetCurrentMousePos(OilCoord* pMousePos) const 02012 { 02013 // Get the Windows screen coordinates of the mouse cursor. 02014 // Convert from screen to window coordinates. 02015 WinCoord pt; 02016 *(wxPoint *)&pt = GetRenderWindow()->ScreenToClient( ::wxGetMousePosition() ); 02017 02018 // If the mouse is outside the view then we can do nothing more. 02019 if (!CurrentSize.Inside(pt)) return FALSE; 02020 02021 // Convert to OIL coordinates. 02022 if (pMousePos!=NULL) 02023 *pMousePos = pt.ToOil(pDocView, TRUE); 02024 02025 // We stored something useful. 02026 return TRUE; 02027 } 02028 02029 02030 /********************************************************************************************* 02031 > void CCamView::SetWorkAreaExtent(const WorkRect& area, BOOL redraw) 02032 02033 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 02034 Created: ages ago 02035 Inputs: A WorkRect describing the new WorkAreaExtent, a boolean which if TRUE 02036 means immediately repaint the view window to reflect the change. 02037 Outputs: - 02038 Returns: - 02039 Purpose: Calculates the size of the RendWnd, setting the "page size" of the 02040 scroll bars accordingly. Sets the scroll range of the scroll bars 02041 to the size of the WorkAreaExtent (note that the Y range is negated 02042 and inverted - the mother of all bodges). 02043 Errors: - 02044 Scope: Public 02045 SeeAlso: CCamView::GetWorkAreaExtent(); CScroller::SetPageSize(); 02046 CScroller::SetScrollRange(); class CRendWnd 02047 02048 **********************************************************************************************/ 02049 02050 void CCamView::SetWorkAreaExtent(const WorkRect& area, BOOL redraw) 02051 { 02052 WorkArea = area; 02053 FIXED16 PixelWidth, PixelHeight; 02054 pDocView->GetPixelSize(&PixelWidth,&PixelHeight); 02055 INT32 HScrRange = (INT32)(WorkArea.Width()/PixelWidth.MakeDouble()); 02056 INT32 VScrRange = (INT32)(WorkArea.Height()/PixelHeight.MakeDouble()); 02057 if (HScrollBar) 02058 HScrollBar->SetScrollbar(HScrollBar->GetThumbPosition(), CurrentSize.GetWidth(), HScrRange, CurrentSize.GetWidth(), true); 02059 if (VScrollBar) 02060 VScrollBar->SetScrollbar(VScrollBar->GetThumbPosition(), CurrentSize.GetHeight(), VScrRange, CurrentSize.GetHeight(), true); 02061 02062 // Should really do something about the redraw param here 02063 // E.g. call the function that causes an immediate repaint of invalid areas 02064 // However, until I see some obvious sign that this is ever necessary I'll 02065 // leave it commented out 02066 // if (redraw) 02067 // { 02068 // if (RenderWindow) 02069 // RenderWindow->Update(); 02070 // } 02071 } 02072 02073 /********************************************************************************************* 02074 > void CCamView::GetScrollOffset(WorkCoord* pOffset) const 02075 02076 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 02077 Created: ages ago 02078 Inputs: - 02079 Outputs: The current scroll offset is written to the passed WorkCoord. 02080 Returns: - 02081 Purpose: Reads the offset from the horizontal and vertical scroll bars, 02082 combining then into a WorkCoord. 02083 Errors: - 02084 Scope: Public 02085 SeeAlso: CCamView::SetScrollOffset(); CScroller::GetScrollPos() 02086 02087 **********************************************************************************************/ 02088 02089 void CCamView::GetScrollOffset(WorkCoord* pOffset) const 02090 { 02091 // TRACEUSER("Gerry", _T("CV::GetScrollOffset\n")); 02092 02093 FIXED16 PixelWidth,PixelHeight; 02094 pDocView->GetPixelSize(&PixelWidth,&PixelHeight); 02095 02096 INT32 HPos = HScrollBar->GetThumbPosition(); 02097 INT32 VPos = VScrollBar->GetThumbPosition(); 02098 02099 // TRACEUSER("Gerry", _T("CanvasPos = (%d, %d)\n"), HPos, VPos); 02100 02101 pOffset->x = XLONG(WorkArea.lo.x + HPos*PixelWidth.MakeDouble()); 02102 pOffset->y = XLONG(WorkArea.hi.y - VPos*PixelHeight.MakeDouble()); 02103 02104 // TRACEUSER("Gerry", _T("ScrollOffset = (%d, %d)\n"), (INT32)(pOffset->x), (INT32)(pOffset->y)); 02105 } 02106 02107 02108 02109 /********************************************************************************************* 02110 > void CCamView::SetScrollOffset(const WorkCoord& pos, BOOL redraw) 02111 02112 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 02113 Created: ages ago 02114 Inputs: The desired scroll offset, in WorkCoords, and a boolean indicating if 02115 TRUE that the view window should be repainted immediately to reflect 02116 the change in scroll position. 02117 Outputs: - 02118 Returns: - 02119 Purpose: Changes the scroll offset in the horizontal and vertical scroll bar. Note 02120 that it DOES NOT immediately scroll the client area, which is only done 02121 when the scroll bars send back a WM_SCROLLEREVENT message to the ScreenView. 02122 Errors: - 02123 Scope: Public 02124 SeeAlso: CCamView::GetScrollOffset; CCamView::OnScrollerEvent() 02125 02126 **********************************************************************************************/ 02127 02128 void CCamView::SetScrollOffset(const WorkCoord& pos, BOOL redraw) 02129 { 02130 // TRACEUSER("Gerry", _T("CV::SetScrollOffset(%d, %d)\n"), (INT32)(pos.x), (INT32)(pos.y)); 02131 FIXED16 PixelWidth,PixelHeight; 02132 pDocView->GetPixelSize(&PixelWidth,&PixelHeight); 02133 02134 // Validate suggested ScrollOffset... 02135 WorkCoord tpos = pos; 02136 WorkRect wrScrollRect = GetMaxScrollRect(); 02137 if (tpos.x < wrScrollRect.lo.x) tpos.x = wrScrollRect.lo.x; 02138 if (tpos.y < wrScrollRect.lo.y) tpos.y = wrScrollRect.lo.y; 02139 if (tpos.x > wrScrollRect.hi.x) tpos.x = wrScrollRect.hi.x; 02140 if (tpos.y > wrScrollRect.hi.y) tpos.y = wrScrollRect.hi.y; 02141 02142 INT32 sx = INT32((tpos.x-WorkArea.lo.x)/PixelWidth .MakeDouble()); 02143 INT32 sy = INT32((WorkArea.hi.y-tpos.y)/PixelHeight.MakeDouble()); 02144 // TRACEUSER("Gerry", _T("Scrolling to (%d, %d)\n"), sx, sy); 02145 02146 HScrollBar->SetThumbPosition(sx); 02147 VScrollBar->SetThumbPosition(sy); 02148 02149 SetCurrentStates(); 02150 if (Status && fSetupDone) 02151 { 02152 WorkCoord temp; 02153 GetScrollOffset(&temp); 02154 Status->SetScrollPos(temp); 02155 if (redraw) 02156 ScrollTo(temp); 02157 } 02158 02159 // Neville 22/8/97 02160 // Somebody is setting the scroll position so make sure that this is set 02161 // Other calls to OnScrollerEvent can be filtered out completely so that a document 02162 // can load in completely but not had one single call to ScrollTo code allowed. Everything 02163 // looks ok but if you scroll slightly then becuase the OldOffset is wrong, usually 0,0, 02164 // a large redraw problem can occur OR the whole drawing will be redrawn needlessly. 02165 // This is called by the document loading code and so when it says it wants this scroll position 02166 // it is generally late enough in the loading process that the 'Fixes bug #1448.' comment 02167 // should have been sorted. 02168 fSetupDone = TRUE; 02169 } 02170 02171 02172 /********************************************************************************************* 02173 > virtual void CCamView::OnInitialUpdate() 02174 02175 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 02176 Created: 19 Jan 1994 02177 Inputs: - 02178 Outputs: - 02179 Returns: - 02180 Purpose: Called when the view must first display the document. Moves this 02181 view/frame to the position given in the ViewState object. 02182 Errors: - 02183 Scope: Protected 02184 SeeAlso: CCamView::SetThisFromViewState; CCamView::SetViewStateFromThis; 02185 DocView::ViewStateChanged 02186 **********************************************************************************************/ 02187 02188 void CCamView::OnUpdate(wxView* sender, wxObject* hint) 02189 { 02190 TRACEUSER("Gerry", _T("CCamView::OnUpdate\n")); 02191 if ( sender==NULL && !fInitialUpdate ) 02192 { 02193 OnInitialUpdate(); 02194 fInitialUpdate = TRUE; 02195 } 02196 wxView::OnUpdate(sender, hint); 02197 } 02198 02199 02200 // 02201 // OnIntialUpdate is no longer called automatically, so we call it instead 02202 // just once from OnUpdate. 02203 // 02204 void CCamView::OnInitialUpdate() 02205 { 02206 TRACEUSER("Gerry", _T("CCamView::OnInitialUpdate\n")); 02207 // Set up current etc. 02208 SetCurrentStates(); 02209 02210 // Check if this view is being created by LoadAppWindowState at the start. If it is 02211 // then pick up the ViewState object ready-made by LoadAppWindowState and set 02212 // this view according to that. 02213 if (pReadyMadeViewState != NULL) 02214 { 02215 TRACEUSER("Gerry", _T("Got pReadyMadeViewState\n")); 02216 02217 // Set the flags saved in temp. storage in the ViewState in the corresponding 02218 // DocView. 02219 DocView* pdv = GetDocViewPtr(); 02220 ERROR3IF(pdv == NULL, "Null DocView* in CCamView::OnInitialUpdate"); 02221 02222 // Deallocate the old ViewState and set the new. 02223 delete SetViewState(pReadyMadeViewState); 02224 02225 // Set these flags as well in the DocView. 02226 pdv->ViewFlags.GridShow = pReadyMadeViewState->_GridShow; 02227 pdv->ViewFlags.GridSnap = pReadyMadeViewState->_GridSnap; 02228 pdv->ViewFlags.ObjectsSnap = pReadyMadeViewState->_ObjectsSnap; 02229 pdv->ViewFlags.MagObjectsSnap = pReadyMadeViewState->_MagObjectsSnap; 02230 pdv->ViewFlags.PrintBorderShow = pReadyMadeViewState->_PrintBorderShow; 02231 pdv->ViewFlags.LogicalView = pReadyMadeViewState->_LogicalView; 02232 pdv->ViewFlags.GuidesSnap = pReadyMadeViewState->_GuidesSnap; 02233 pdv->ViewFlags.GuidesShow = pReadyMadeViewState->_GuidesShow; 02234 02235 // Make sure we set this view from the view-state, not the other way around. 02236 pReadyMadeViewState = NULL; 02237 Status->IsNewView = FALSE; 02238 } 02239 02240 // Force the DocView to set the work area extent. 02241 pDocView->ViewStateChanged(); 02242 02243 if (HScrollBar) 02244 { 02245 // Calculate the scroller page & line sizes, and its range, and make sure the 02246 // work area extent is updated. 02247 INT32 Width = CurrentSize.GetWidth(); 02248 HScrollBar->SetScrollbar(HScrollBar->GetThumbPosition(), Width, HScrollBar->GetRange(), Width); 02249 } 02250 02251 if (VScrollBar) 02252 { 02253 INT32 Height = CurrentSize.GetHeight(); 02254 VScrollBar->SetScrollbar(VScrollBar->GetThumbPosition(), Height, VScrollBar->GetRange(), Height); 02255 } 02256 02257 // Either make this view conform to the ViewState, or update the ViewState with 02258 // information about this view, depending on whether the view is new or (re)loaded. 02259 if (Status->IsNewView) 02260 { 02261 SetViewStateFromThis(); 02262 pDocView->OnNewView(); // give the DocView a shot 02263 } 02264 else 02265 { 02266 SetThisFromViewState(); 02267 pDocView->OnLoadedView(); // let kernel have its say 02268 } 02269 02270 PORTNOTE("other","CCamView::OnInitialUpdate - code removed") 02271 #ifndef EXCLUDE_FROM_XARALX 02272 // RALPH 02273 if (GetParentFrame()) 02274 { 02275 #if (_OLE_VER >= 0x200) 02276 // In OLE builds only do this for non-embedded docs, as OnShowDocument will handle it 02277 // for embedded docs. 02278 if (!GetDocument()->IsServer()) 02279 #endif 02280 { 02281 // Apply preferences. To begin, maximise this view if it is the only one around. 02282 BOOL fAppIsIcon = GetMainFrame()->IsIconic(); 02283 if (HowMany() == 1) 02284 { 02285 // This flag is TRUE during workspace restoration of more than one doc. We don't 02286 // want to maximise any views if its TRUE. 02287 extern BOOL fDontMaximiseViews; 02288 if (ZoomSingleView && !fAppIsIcon && !fDontMaximiseViews) 02289 ((CMDIChildWnd*) GetParentFrame())->MDIMaximize(); 02290 } 02291 else 02292 { 02293 // Otherwise, if a view is already maximised, un-maximise it so that this 02294 // view is visible. 02295 if (UnzoomOnNewView || fAppIsIcon) 02296 { 02297 // Find out the active view, which must be the one maximised, if any are. 02298 BOOL fIsMaxed; 02299 CMDIFrameWnd* pMainWnd = ((CMDIChildWnd*) GetParentFrame())->GetMDIFrame(); 02300 ENSURE(pMainWnd, "No MDI frame window in CCamView::OnShowWindow!"); 02301 CMDIChildWnd* pMaxiWnd = pMainWnd->MDIGetActive(&fIsMaxed); 02302 02303 // If it is maximised then restore it. 02304 if (fIsMaxed && pMaxiWnd != NULL) 02305 { 02306 wxView* pv = pMaxiWnd->GetActiveView(); 02307 if (pv && pv->GetDocument() && 02308 ((CCamDoc*) pv->GetDocument())->IsUntouched()) 02309 { 02310 TRACEUSER( "JustinF", _T("MDI Restore in CCamView::OnInitialUpdate\n")); 02311 pMaxiWnd->MDIRestore(); 02312 } 02313 } 02314 } 02315 } 02316 } 02317 } 02318 #ifdef _DEBUG 02319 else 02320 { 02321 TRACEUSER( "JustinF", _T("\t- no parent frame in CCamView::OnInitialUpdate\n")); 02322 } 02323 #endif 02324 #endif 02325 02326 // Make sure the render window gets repainted and inform the kernel that something 02327 // has happened. 02328 GetRenderWindow()->Refresh(false); 02329 pDocView->ViewStateChanged(); 02330 02331 // Indicate that we have set the position, size, focus etc so OnActivateView is safe 02332 // to update the HasFocus fields of ViewStates. 02333 fSetupDone = TRUE; 02334 02335 #if (_OLE_VER >= 0x200) 02336 02337 // Check if the document wants to zoom to the page. This is the best place to 02338 // do this as everything should now be stable. 02339 LPCTSTR lpcszZoomOp = GetDocument()->GetInitialZoom(); 02340 if (lpcszZoomOp) 02341 { 02342 // Remember the old prev. zoom setting. 02343 INT32 nPrev; 02344 FIXED16 fxPrev; 02345 WorkCoord wcPrev; 02346 nPrev = pDocView->GetPrevZoomIndex(); 02347 fxPrev = pDocView->GetPrevZoomScale(); 02348 wcPrev = pDocView->GetPrevZoomOffset(); 02349 02350 // There is, so zoom it to show the new page bounds. Set-up the kernel. 02351 DocView* pOldCurrent = DocView::GetCurrent(); 02352 pDocView->SetCurrent(); 02353 02354 // Perform the Zoom-to-Page Operation (it's non-undo-able). 02355 OpDescriptor* pOp = OpDescriptor::FindOpDescriptor((LPTSTR) lpcszZoomOp); 02356 ERROR3IF(!pOp, "Can't find the Zoom Operation in CCamView::OnInitialUpdate"); 02357 pOp->Invoke(0); 02358 02359 // Restore the old prev. zoom setting. 02360 pDocView->SetPrevZoomIndex(nPrev); 02361 pDocView->SetPrevZoomScale(fxPrev); 02362 pDocView->SetPrevZoomOffset(wcPrev); 02363 } 02364 02365 #endif 02366 } 02367 02368 02369 02370 /********************************************************************************************* 02371 > void CCamView::OnActivateView(BOOL bActivate, wxView* pActiveView, wxView* pDeactiveView) 02372 02373 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 02374 Created: ages ago 02375 Inputs: A boolean which if TRUE means that this view is being activated, if FALSE 02376 that this view is being deactivated; two pointers to the CView objects which 02377 are being activated/deactivated. 02378 Outputs: Possibly changes the pointed-to views. 02379 Returns: - 02380 Purpose: Called by MFC when a view gains or loses the input focus, either due to the 02381 the user clicking about, or another application popping up a window etc etc. 02382 I would just like to point out that this MFC function is the most brain-damaged 02383 Microsoft have come up so far. It's documentation bears no resemblance to 02384 the way the function is called/used - for example, as far as I can see, the 02385 two CView* parameters are NEVER different! 02386 Errors: - 02387 Scope: Protected 02388 SeeAlso: Pretty unique, this one, so I can't think of anything to put here. 02389 02390 **********************************************************************************************/ 02391 02392 void CCamView::OnActivateView( bool bActivate, wxView* pActiveView, wxView* pDeactiveView ) 02393 { 02394 TRACEUSER("Gerry", _T("CCamView::OnActivateView(%s) - 0x%08x\n"), bActivate ? _T("true") : _T("false"), this); 02395 02396 if ( !pDocView ) 02397 { 02398 TRACE( _T("CCamView::OnActivateView - Warning: pDocView is NULL\n") ); 02399 return; 02400 } 02401 02402 if (bActivate) SetCurrentStates(); 02403 02404 Document* KernelDoc = NULL; 02405 if (pDocView) KernelDoc = pDocView->GetDoc(); 02406 02407 // MFC does some hidden stuff here . . . 02408 wxView::OnActivateView( bActivate, pActiveView, pDeactiveView ); 02409 02410 // Trigger off some messages into the kernel. 02411 if (bActivate) 02412 { 02413 // make sure the global preference reflects the current state 02414 SetDefaultRulersState(Status->RulersVisible); 02415 SetDefaultScrollersState(Status->ScrollersVisible); 02416 02417 // Update our records of who is top-most and set the keyboard input focus to 02418 // the rendering child window. 02419 GetRenderWindow()->SetFocus(); 02420 02421 // Inform the kernel that the view's Z-order has changed. This sets the selected 02422 // View, Document, and spread, to legal values. 02423 Document::SetSelectedViewAndSpread(KernelDoc, pDocView, NULL); 02424 } 02425 else 02426 { 02427 TRACEUSER("Gerry", _T("Deactivating the view\n")); 02428 02429 // Lets just try setting no selected for the time being but only if this view is the selected one 02430 if (DocView::GetSelected() == pDocView) 02431 { 02432 PORTNOTE("other", "CCamView::OnActivateView(false) now setting no selected doc and view") 02433 Document::SetNoSelectedViewAndSpread(); 02434 } 02435 else 02436 { 02437 TRACEUSER("Gerry", _T("Not the selected view\n")); 02438 } 02439 } 02440 } 02441 02442 02443 /********************************************************************************************* 02444 > void CCamView::SetViewStateFromThis() const 02445 02446 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 02447 Created: ages ago 02448 Inputs: - 02449 Outputs: - 02450 Returns: - 02451 Purpose: Called by a virgin ScreenView, ie. a view onto a new, unedited 02452 document. The function reads the attributes of the view window 02453 from the operating system, converts them into a device- 02454 independent form, and stores them in the ViewState. 02455 Errors: - 02456 Scope: Private 02457 SeeAlso: CCamView::OnInitialUpdate; CCamView::SetThisFromViewState(); 02458 DocView::ViewStateChanged(); class ViewState 02459 02460 **********************************************************************************************/ 02461 02462 void CCamView::SetViewStateFromThis() const 02463 { 02464 TRACEUSER("Gerry", _T("SetViewStateFromThis\n")); 02465 02466 // Set the current docview. 02467 pDocView->SetCurrent(); 02468 02469 // Set most of the ViewState according to the current state (the default) of this 02470 // ScreenView. 02471 UpdateViewPosition(); 02472 02473 // Make sure the scale factor is accurate. 02474 FIXED16 scale = pDocView->GetViewScale(); 02475 if (scale != Status->ViewScale) Status->ViewScale = scale; 02476 02477 // Record the current scroller position. 02478 WorkCoord temp; 02479 GetScrollOffset(&temp); 02480 Status->SetScrollPos(temp); 02481 02482 if( NULL != GetParentFrame() ) 02483 { 02484 // Record the top-most attribute of the frame window. 02485 PORTNOTE("other","Removed WM_TOPMOSTENQUIRY usage - is this really needed?") 02486 #ifndef EXCLUDE_FROM_XARALX 02487 Status->AlwaysOnTop = m_pFrame->SendMessage( WM_TOPMOSTENQUIRY ); 02488 #endif 02489 } 02490 } 02491 02492 02493 02494 02495 /********************************************************************************************* 02496 > void CCamView::SetThisFromViewState() 02497 02498 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 02499 Created: ages ago 02500 Inputs: - 02501 Outputs: - 02502 Returns: - 02503 Purpose: Move and resize the ScreenView according to the (device-independent) 02504 settings of a ViewState object. This typically happens when a new 02505 view is opened on a saved document. 02506 Errors: - 02507 Scope: Private 02508 SeeAlso: CCamView::SetViewStateFromThis(); CCamView::OnInitialUpdate() 02509 02510 **********************************************************************************************/ 02511 02512 void CCamView::SetThisFromViewState() 02513 { 02514 TRACEUSER("Gerry", _T("SetThisFromViewState\n")); 02515 02516 PORTNOTE("other","CCamView::SetThisFromViewState - do nothing"); 02517 #ifndef EXCLUDE_FROM_XARALX 02518 // Get a pointer to this view's frame window. 02519 wxMDIChildFrame *pframewnd = (wxMDIChildFrame *)GetParentFrame(); 02520 //ENSURE(pframewnd != NULL, "Found a ScreenView without a frame window?!?"); 02521 02522 // Fill in a Windows placement structure with some converted positions from the 02523 // ViewState object, and set the placement of the parent frame window accordingly. 02524 WINDOWPLACEMENT wp; 02525 wp.length = sizeof(wp); 02526 wp.flags = WPF_SETMINPOSITION; 02527 wp.ptMaxPosition.x = wp.ptMaxPosition.y = 0; 02528 02529 // Work out how to display the window, either as an icon, maximised, or just normal. 02530 // Note that it is possible for a maximised window to be iconised without being 02531 // restore first. 02532 if (Status->IsMinimised) 02533 { 02534 wp.showCmd = SW_SHOWMINIMIZED; // display as an icon 02535 if (Status->IsMaximised) 02536 { 02537 wp.flags |= WPF_RESTORETOMAXIMIZED; // go from icon to maximised 02538 } 02539 } 02540 else if (Status->IsMaximised) 02541 { 02542 wp.showCmd = SW_SHOWMAXIMIZED; // display maximised 02543 } 02544 else 02545 { 02546 wp.showCmd = SW_SHOWNORMAL; // display normally 02547 } 02548 02549 Coord2POINT(Status->IconPoint, &wp.ptMinPosition); 02550 Rect2RECT(Status->ViewRect, &wp.rcNormalPosition); 02551 02552 //RALPH 02553 if(pframewnd) 02554 pframewnd->SetWindowPlacement(&wp); 02555 #endif 02556 02557 // Needs to set the window position and size 02558 02559 // Set the scroll offset. 02560 OldOffset = Status->GetScrollPos(); 02561 SetScrollOffset(OldOffset); 02562 02563 // Set the scale factor. 02564 pDocView->SetViewScale(Status->ViewScale); 02565 02566 PORTNOTE("other","CCamView::SetThisFromViewState - do nothing"); 02567 #ifndef EXCLUDE_FROM_XARALX 02568 // If the view was "always on top" then fake a user selection of the appropriate 02569 // menu option. 02570 // RALPH 02571 if (Status->AlwaysOnTop && GetParentFrame()) 02572 { 02573 GetParentFrame()->PostMessage(WM_SYSCOMMAND, _R(IDM_ALWAYSONTOP)); 02574 } 02575 #endif 02576 } 02577 02578 02579 /******************************************************************************************** 02580 > void CCamView::UpdateViewPosition() const 02581 02582 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 02583 Created: 12/4/94 02584 Inputs: - 02585 Outputs: - 02586 Returns: - 02587 Purpose: Updates the ViewState object shared between this ScreenView and its 02588 associated DocView with the new size of the view etc. 02589 Errors: - 02590 SeeAlso: - 02591 ********************************************************************************************/ 02592 02593 void CCamView::UpdateViewPosition() const 02594 { 02595 TRACEUSER("Gerry", _T("CCamView::UpdateViewPosition\n")); 02596 02597 ENSURE(Status != NULL, "No ViewState object in CCamView::UpdateViewPosition!"); 02598 02599 wxRect rc; 02600 wxFrame* pFrame = GetParentFrame(); 02601 if(pFrame) 02602 { 02603 // Get the rectangle of the parent's MDICLIENT window. All child window sizes and 02604 // positions are calculated as relative to this. This is more accurate than just 02605 // taking the size of the main frame window as a whole, including menus, title bar etc. 02606 GetMainFrame()->GetClientSize( &rc.width, &rc.height ); 02607 wxRect2Rect(rc, &Status->ParentRect); 02608 } 02609 02610 if(pFrame) 02611 rc = pFrame->GetRect(); 02612 02613 // Fill in the ViewState with the position of the normal and iconised 02614 // window. The maximised position of the window does not need to be 02615 // stored as it always fills the whole MDI client area of its parent. 02616 wxRect2Rect(rc, &Status->ViewRect); 02617 02618 Status->IsMinimised = Status->IsMaximised = FALSE; 02619 02620 PORTNOTE("other","CCamView::UpdateViewPosition - removed GetWindowPlacement"); 02621 #ifndef EXCLUDE_FROM_XARALX 02622 ENSURE(Status != NULL, "No ViewState object in CCamView::UpdateViewPosition!"); 02623 02624 // Get the size of the screen. We don't use this for anything, but I'm afraid to 02625 // take it out in case something breaks! 02626 // LH 31/08/2005 - Removed, if something breaks I'll revisit! 02627 wxRect rc; 02628 // GetDesktopWindow()->GetWindowRect( &rc ); 02629 // RECT2Rect(rc, &Status->ScreenRect); 02630 02631 wxFrame *pframewnd = GetParentFrame(); 02632 02633 if(pframewnd) 02634 { 02635 // Get the rectangle of the parent's MDICLIENT window. All child window sizes and 02636 // positions are calculated as relative to this. This is more accurate than just 02637 // taking the size of the main frame window as a whole, including menus, title bar etc. 02638 GetMainFrame()->GetClientSize( &rc.width, &rc.height ); 02639 RECT2Rect(rc, &Status->ParentRect); 02640 } 02641 02642 // Get the placement information for this view (MDI child) window. Note 02643 // that because it is a child window, the position is taken relative to the 02644 // client area of its parent. 02645 WINDOWPLACEMENT wp; 02646 wp.length = sizeof(wp); 02647 02648 02649 //ENSURE(pframewnd != NULL, "Found a ScreenView without a frame window?!?"); 02650 if(pframewnd) 02651 pframewnd->GetWindowPlacement(&wp); 02652 02653 // Fill in the ViewState with the position of the normal and iconised 02654 // window. The maximised position of the window does not need to be 02655 // stored as it always fills the whole MDI client area of its parent. 02656 RECT2Rect(wp.rcNormalPosition, &Status->ViewRect); 02657 POINT2Coord(wp.ptMinPosition, &Status->IconPoint); 02658 02659 // Update the mini/maxi flags. Note that it is possible for IsMinised and IsMaximised 02660 // to both be TRUE, if a maximised window has been iconised (but NOT if an iconised 02661 // window has been maximised!). 02662 if (wp.showCmd == SW_SHOWMINIMIZED) 02663 { 02664 Status->IsMinimised = TRUE; 02665 } 02666 else if (wp.showCmd == SW_SHOWMAXIMIZED) 02667 { 02668 Status->IsMinimised = FALSE; 02669 Status->IsMaximised = TRUE; 02670 } 02671 else // must be SW_SHOWNORMAL, ie. "restored" 02672 { 02673 Status->IsMinimised = Status->IsMaximised = FALSE; 02674 } 02675 #endif 02676 } 02677 02678 02679 /******************************************************************************************** 02680 > void CCamView::ShowScrollers(BOOL ShowOrHide) 02681 02682 Author: Chris_Parks (Xara Group Ltd) <camelotdev@xara.com> 02683 Created: 2/11/94 02684 Inputs: - 02685 Outputs: - 02686 Returns: - 02687 Purpose: Hide or Show Scrollers. 02688 Errors: - 02689 SeeAlso: - 02690 ********************************************************************************************/ 02691 02692 void CCamView::ShowScrollers(BOOL Show) 02693 { 02694 // Set flags and Show/Hide the Scrollers 02695 bool bShow = Show ? true : false; 02696 VScrollBar->Show(bShow); 02697 HScrollBar->Show(bShow); 02698 Status->ScrollersVisible = Show; 02699 02700 // call OnSize directly to force new layout 02701 wxSize Size; 02702 m_pFrame->GetSize(&Size.x, &Size.y); 02703 TRACEUSER("Gerry", _T("Force an OnSize here (%d, %d)\n"), Size.x, Size.y); 02704 02705 wxSizeEvent evSize(Size, 0); 02706 OnSize(evSize); 02707 } 02708 02709 02710 02711 /******************************************************************************************** 02712 > void CCamView::ShowRulers(BOOL ShowOrHide) 02713 02714 Author: Chris_Parks (Xara Group Ltd) <camelotdev@xara.com> 02715 Created: 2/11/94 02716 Inputs: - 02717 Outputs: - 02718 Returns: - 02719 Purpose: Hide or Show Rulers. 02720 Errors: - 02721 SeeAlso: - 02722 ********************************************************************************************/ 02723 02724 void CCamView::ShowRulers(BOOL Show) 02725 { 02726 // WEBSTER - markn 15/1/97 02727 // No rulers in Webster 02728 #ifndef WEBSTER 02729 #if !defined(EXCLUDE_FROM_RALPH) 02730 if (!VRuler||!HRuler) 02731 return; 02732 02733 // Set flags and Show/Hide the Rulers 02734 if (VRuler) 02735 VRuler->ShowRuler(Show); 02736 02737 if (HRuler) 02738 HRuler->ShowRuler(Show); 02739 02740 if (OGadget) 02741 OGadget->ShowGadget(Show); 02742 02743 Status->RulersVisible = Show; 02744 02745 // call OnSize directly to force new layout 02746 wxSize Size=wxDefaultSize; 02747 m_pFrame->GetSize(&Size.x, &Size.y); 02748 wxSizeEvent evSize(Size, 0); 02749 OnSize(evSize); 02750 #endif 02751 #endif // WEBSTER 02752 } 02753 02754 02755 02756 /********************************************************************************************* 02757 > BOOL CCamView::AreRulersVisible() 02758 02759 Author: Chris_Snook (Xara Group Ltd) <camelotdev@xara.com> 02760 Created: ages ago 02761 Inputs: - 02762 Outputs: - 02763 Returns: Ruler Visible state. 02764 Purpose: - 02765 Errors: - 02766 Scope: Public 02767 02768 **********************************************************************************************/ 02769 02770 BOOL CCamView::AreRulersVisible() 02771 { 02772 #if !defined(EXCLUDE_FROM_RALPH) 02773 if(Status) 02774 return Status->RulersVisible; 02775 #endif 02776 return FALSE; 02777 }; 02778 02779 /********************************************************************************************* 02780 > BOOL CCamView::AreScrollersVisible() 02781 02782 Author: Chris_Snook (Xara Group Ltd) <camelotdev@xara.com> 02783 Created: ages ago 02784 Inputs: - 02785 Outputs: - 02786 Returns: Scroller Visible state. 02787 Purpose: - 02788 Errors: - 02789 Scope: Public 02790 02791 **********************************************************************************************/ 02792 02793 BOOL CCamView::AreScrollersVisible() 02794 { 02795 if(Status) 02796 return Status->ScrollersVisible; 02797 return FALSE; 02798 } 02799 02800 02801 /********************************************************************************************* 02802 > BOOL CCamView::IsMouseOverRuler() 02803 02804 Author: Chris_Snook (Xara Group Ltd) <camelotdev@xara.com> 02805 Created: 1/10/95 02806 Inputs: - 02807 Outputs: - 02808 Returns: enum MouseOverRulerHit can be OVER_NO_RULERS, 02809 OVER_HORIZONTAL, 02810 OVER_VERTICAL, 02811 OVER_ORIGIN_GADGET. 02812 Purpose: - 02813 Errors: - 02814 Scope: Public 02815 02816 **********************************************************************************************/ 02817 02818 MouseOverRulerHit CCamView::IsMouseOverRuler() 02819 { 02820 #if !defined(EXCLUDE_FROM_RALPH) 02821 // check that we have some rulers 02822 if (!HRuler||!VRuler||!OGadget) 02823 return OVER_NO_RULERS; 02824 02825 // Find the window the pointer is over 02826 wxWindow* pWindow = ::wxChildWindowFromPoint(::wxGetMousePosition(), false, -1); 02827 02828 // check the HWND against the rulers 02829 if (pWindow == (wxWindow*)HRuler) 02830 return OVER_HORIZONTAL; 02831 else if (pWindow == (wxWindow*)VRuler) 02832 return OVER_VERTICAL; 02833 else if (pWindow == (wxWindow*)OGadget) 02834 return OVER_ORIGIN_GADGET; 02835 #endif 02836 02837 return OVER_NO_RULERS; 02838 }; 02839 02840 02841 02842 02843 /********************************************************************************************* 02844 > afx_msg void CCamView::OnLButtonDown(UINT32 nFlags, wxPoint point) 02845 02846 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 02847 Created: ages ago 02848 Inputs: Flags describing which buttons & keys were down when the message was sent; 02849 the coordinates of the mouse cursor. 02850 Outputs: - 02851 Returns: - 02852 Purpose: Called by MFC upon receipt of a left-button-down mouse message. Finds out 02853 which other buttons are down (eg. SHIFT) and passes the message on to the kernel. 02854 Note that the mouse message will have originally come from the RendWnd object, a 02855 child window of ScreenView. 02856 Errors: - 02857 Scope: Protected 02858 SeeAlso: class CRendWnd; CCamView::HandleDragEvent() 02859 02860 **********************************************************************************************/ 02861 02862 void CCamView::OnLButtonDown( wxMouseEvent &event ) 02863 { 02864 DontSkipNextMouse(); 02865 // If the event is not from the RenderWindow then skip it 02866 //TRACEUSER("Phil", _T("OnLButtonDown\n")); 02867 INT32 nID = event.GetId(); 02868 if (nID != WID_RENDERWINDOW) 02869 { 02870 // TRACEUSER("Gerry", _T("Ignoring mouse event in window %d\n"), nID); 02871 event.Skip(); 02872 return; 02873 } 02874 02875 wxPoint point = event.GetPosition(); 02876 UINT32 nFlags = ClickModifiers::SynthesizeMouseEventFlags(event); 02877 02878 #if !defined(EXCLUDE_FROM_RALPH) && !defined(EXCLUDE_FROM_XARALX) 02879 // WEBSTER - markn 25/4/97 02880 // No pen stuff required in Webster 02881 // Taken out by vector stroking code Neville 2/10/97 02882 #ifdef VECTOR_STROKING 02883 // Setup pressure if pen active 02884 (Camelot.GetPressurePen())->CheckMouseMessage(WM_LBUTTONDOWN, point); 02885 #endif // VECTOR_STROKING 02886 #endif 02887 02888 // Support triple clicks 02889 wxRect ClickBounds( LastDoubleClickPos.x - LocalEnvironment::GetXMouseDoubleClickMove(), 02890 LastDoubleClickPos.y - LocalEnvironment::GetYMouseDoubleClickMove(), 02891 LocalEnvironment::GetXMouseDoubleClickMove() * 2, 02892 LocalEnvironment::GetYMouseDoubleClickMove() * 2 ); 02893 02894 MonotonicTime ThisClickTime( event.GetTimestamp() ); 02895 MonotonicTime ClickGap(LocalEnvironment::GetMouseDoubleClickDelay()); 02896 02897 // Is click within allowed movement rectangle and permitted time delay 02898 INT32 TimeDelay = (ThisClickTime - TimeOfLastClick); 02899 if( ClickBounds.Inside( point ) && ( TimeDelay <= (INT32)ClickGap ) ) 02900 ThisSingleIsTriple = TRUE; 02901 else 02902 ThisSingleIsTriple = FALSE; 02903 02904 // Deal with the click 02905 HandleDragEvent( MK_LBUTTON, nFlags, point, CLICKTYPE_SINGLE ); 02906 02907 TimeOfLastClick.Sample(); 02908 } 02909 02910 /********************************************************************************************* 02911 > afx_msg void CCamView::OnMButtonDown(UINT32 nFlags, wxPoint point) 02912 02913 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 02914 Created: ages ago 02915 Inputs: Flags describing which buttons & keys were down when the message was sent; 02916 the coordinates of the mouse cursor. 02917 Outputs: - 02918 Returns: - 02919 Purpose: Called by MFC upon receipt of a middle-button-down mouse message. Finds out 02920 which other buttons are down (eg. SHIFT) and passes the message on to the kernel. 02921 Note that the mouse message will have originally come from the RendWnd object, a 02922 child window of ScreenView. 02923 Errors: - 02924 Scope: Protected 02925 SeeAlso: class CRendWnd; CCamView::HandleDragEvent() 02926 02927 **********************************************************************************************/ 02928 02929 void CCamView::OnMButtonDown( wxMouseEvent &event ) 02930 { 02931 DontSkipNextMouse(); 02932 // If the event is not from the RenderWindow then skip it 02933 INT32 nID = event.GetId(); 02934 if (nID != WID_RENDERWINDOW) 02935 { 02936 // TRACEUSER("Gerry", _T("Ignoring mouse event in window %d\n"), nID); 02937 event.Skip(); 02938 return; 02939 } 02940 02941 wxPoint point = event.GetPosition(); 02942 UINT32 nFlags = ClickModifiers::SynthesizeMouseEventFlags(event); 02943 02944 #if !defined(EXCLUDE_FROM_RALPH) && !defined(EXCLUDE_FROM_XARALX) 02945 // WEBSTER - markn 25/4/97 02946 // No pen stuff required in Webster 02947 // Taken out by vector stroking code Neville 2/10/97 02948 #ifdef VECTOR_STROKING 02949 (Camelot.GetPressurePen())->CheckMouseMessage(WM_MBUTTONDOWN, point); 02950 #endif // VECTOR_STROKING 02951 #endif 02952 HandleDragEvent(MK_MBUTTON, nFlags, point, CLICKTYPE_SINGLE); 02953 } 02954 02955 /********************************************************************************************* 02956 > afx_msg void CCamView::OnRButtonDown(UINT32 nFlags, wxPoint point) 02957 02958 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 02959 Created: ages ago 02960 Inputs: Flags describing which buttons & keys were down when the message was sent; 02961 the coordinates of the mouse cursor. 02962 Outputs: - 02963 Returns: - 02964 Purpose: Same as for CCamView::OnLButtonDown(), but for the right mouse button. 02965 Errors: - 02966 Scope: Protected 02967 SeeAlso: class CRendWnd; CCamView::HandleDragEvent(); CCamView::OnLButtonDown() 02968 02969 **********************************************************************************************/ 02970 02971 void CCamView::OnRButtonDown( wxMouseEvent &event ) 02972 { 02973 DontSkipNextMouse(); 02974 // If the event is not from the RenderWindow then skip it 02975 INT32 nID = event.GetId(); 02976 if (nID != WID_RENDERWINDOW) 02977 { 02978 // TRACEUSER("Gerry", _T("Ignoring mouse event in window %d\n"), nID); 02979 event.Skip(); 02980 return; 02981 } 02982 02983 wxPoint point = event.GetPosition(); 02984 UINT32 nFlags = ClickModifiers::SynthesizeMouseEventFlags(event); 02985 02986 #if !defined(EXCLUDE_FROM_RALPH) && !defined(EXCLUDE_FROM_XARALX) 02987 // WEBSTER - markn 25/4/97 02988 // No pen stuff required in Webster 02989 // Taken out by vector stroking code Neville 2/10/97 02990 #ifdef VECTOR_STROKING 02991 (Camelot.GetPressurePen())->CheckMouseMessage( WM_RBUTTONDOWN, event.GetPosition() ); 02992 #endif // VECTOR_STROKING 02993 #endif 02994 HandleDragEvent(MK_RBUTTON, nFlags, point, CLICKTYPE_SINGLE); 02995 } 02996 02997 02998 /********************************************************************************************* 02999 > afx_msg void CCamView::OnLButtonUp(UINT32 nFlags, wxPoint point) 03000 03001 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 03002 Created: ages ago 03003 Inputs: Flags describing which buttons & keys were down when the message was sent; 03004 the coordinates of the mouse cursor 03005 Outputs: - 03006 Returns: - 03007 Purpose: Passes the event on to HandleButtonUp() 03008 Errors: - 03009 Scope: Protected 03010 SeeAlso: class CRendWnd; CCamView::OnLButtonDown(); CCamView::GetClickMods(); 03011 DocView::DragFinished(); CCamView::HandleButtonUp() 03012 03013 **********************************************************************************************/ 03014 03015 void CCamView::OnLButtonUp(wxMouseEvent &event) 03016 { 03017 DontSkipNextMouse(); 03018 // If the event is not from the RenderWindow then skip it 03019 //TRACEUSER("Phil", _T("OnLButtonUp\n")); 03020 INT32 nID = event.GetId(); 03021 if (nID != WID_RENDERWINDOW) 03022 { 03023 // TRACEUSER("Gerry", _T("Ignoring mouse event in window %d\n"), nID); 03024 event.Skip(); 03025 return; 03026 } 03027 03028 HandleButtonUp(MK_LBUTTON, event); 03029 } 03030 03031 03032 03033 03034 /********************************************************************************************* 03035 > afx_msg void CCamView::OnMButtonUp(UINT32 nFlags, wxPoint point) 03036 03037 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 03038 Created: ages ago 03039 Inputs: Flags describing which buttons & keys were down when the message was sent; 03040 the coordinates of the mouse cursor. 03041 Outputs: - 03042 Returns: - 03043 Purpose: Passes the event on to HandleButtonUp(). 03044 Errors: - 03045 Scope: Protected 03046 SeeAlso: class CRendWnd; CCamView::OnMButtonDown(); CCamView::GetClickMods(); 03047 DocView::DragFinished(); CCamView::HandleButtonUp() 03048 03049 **********************************************************************************************/ 03050 03051 void CCamView::OnMButtonUp(wxMouseEvent &event) 03052 { 03053 DontSkipNextMouse(); 03054 // If the event is not from the RenderWindow then skip it 03055 INT32 nID = event.GetId(); 03056 if (nID != WID_RENDERWINDOW) 03057 { 03058 // TRACEUSER("Gerry", _T("Ignoring mouse event in window %d\n"), nID); 03059 event.Skip(); 03060 return; 03061 } 03062 03063 HandleButtonUp(MK_MBUTTON, event); 03064 } 03065 03066 03067 03068 03069 /********************************************************************************************* 03070 > afx_msg void CCamView::OnRButtonUp(UINT32 nFlags, wxPoint point) 03071 03072 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 03073 Created: ages ago 03074 Inputs: Flags describing which buttons & keys were down when the message was sent; 03075 the coordinates of the mouse cursor. 03076 Outputs: - 03077 Returns: - 03078 Purpose: Same as CCamView::OnLButtonUp(), but for the right mouse button. 03079 Errors: - 03080 Scope: Protected 03081 SeeAlso: class CRendWnd; CCamView::OnRButtonDown(); CCamView::GetClickMods(); 03082 DocView::DragFinished(); CCamView::HandleButtonUp() 03083 03084 **********************************************************************************************/ 03085 03086 void CCamView::OnRButtonUp( wxMouseEvent &event ) 03087 { 03088 DontSkipNextMouse(); 03089 // If the event is not from the RenderWindow then skip it 03090 INT32 nID = event.GetId(); 03091 if (nID != WID_RENDERWINDOW) 03092 { 03093 // TRACEUSER("Gerry", _T("Ignoring mouse event in window %d\n"), nID); 03094 event.Skip(); 03095 return; 03096 } 03097 03098 HandleButtonUp(MK_RBUTTON, event); 03099 } 03100 03101 03102 03103 03104 /********************************************************************************************* 03105 > afx_msg void CCamView::OnLButtonDblClk(UINT32 nFlags, wxPoint point) 03106 03107 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 03108 Created: ages ago 03109 Inputs: Flags describing which buttons & keys were down when the message was sent; 03110 the coordinates of the mouse cursor. 03111 Outputs: - 03112 Returns: - 03113 Purpose: Passes a left-button double-click to CCamView::HandleDragEvent(). 03114 Errors: - 03115 Scope: Protected 03116 SeeAlso: class CRendWnd; CCamView::HandleDragEvent() 03117 03118 **********************************************************************************************/ 03119 03120 void CCamView::OnLButtonDblClk(wxMouseEvent &event) 03121 { 03122 DontSkipNextMouse(); 03123 // If the event is not from the RenderWindow then skip it 03124 INT32 nID = event.GetId(); 03125 if (nID != WID_RENDERWINDOW) 03126 { 03127 // TRACEUSER("Gerry", _T("Ignoring mouse event in window %d\n"), nID); 03128 event.Skip(); 03129 return; 03130 } 03131 03132 wxPoint point = event.GetPosition(); 03133 UINT32 nFlags = ClickModifiers::SynthesizeMouseEventFlags(event); 03134 03135 // Support quad clicks 03136 wxRect ClickBounds( LastDoubleClickPos.x-LocalEnvironment::GetXMouseDoubleClickMove(), 03137 LastDoubleClickPos.y-LocalEnvironment::GetYMouseDoubleClickMove(), 03138 LastDoubleClickPos.x+LocalEnvironment::GetXMouseDoubleClickMove(), 03139 LastDoubleClickPos.y+LocalEnvironment::GetYMouseDoubleClickMove()); 03140 MonotonicTime ThisClickTime( event.GetTimestamp() ); 03141 MonotonicTime ClickGap(LocalEnvironment::GetMouseDoubleClickDelay()); 03142 // Is click within allowed movement rectangle and permitted time delay 03143 INT32 TimeDelay = (ThisClickTime - TimeOfLastClick); 03144 if (ClickBounds.Inside( point ) && (TimeDelay <= (INT32)ClickGap)) 03145 ThisDoubleIsQuad = TRUE; 03146 else 03147 ThisDoubleIsQuad = FALSE; 03148 03149 HandleDragEvent(MK_LBUTTON, nFlags, point, CLICKTYPE_DOUBLE); 03150 03151 TimeOfLastClick.Sample(); 03152 LastDoubleClickPos = point; 03153 } 03154 03155 03156 03157 03158 /********************************************************************************************* 03159 > afx_msg void CCamView::OnMButtonDblClk(UINT32 nFlags, wxPoint point) 03160 03161 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 03162 Created: ages ago 03163 Inputs: Flags describing which buttons & keys were down when the message was sent; 03164 the coordinates of the mouse cursor. 03165 Outputs: - 03166 Returns: - 03167 Purpose: Passes a middle-button double-click to CCamView::HandleDragEvent(). 03168 Errors: - 03169 Scope: Protected 03170 SeeAlso: class CRendWnd; CCamView::HandleDragEvent() 03171 03172 **********************************************************************************************/ 03173 03174 void CCamView::OnMButtonDblClk(wxMouseEvent &event) 03175 { 03176 DontSkipNextMouse(); 03177 // If the event is not from the RenderWindow then skip it 03178 INT32 nID = event.GetId(); 03179 if (nID != WID_RENDERWINDOW) 03180 { 03181 // TRACEUSER("Gerry", _T("Ignoring mouse event in window %d\n"), nID); 03182 event.Skip(); 03183 return; 03184 } 03185 03186 wxPoint point = event.GetPosition(); 03187 UINT32 nFlags = ClickModifiers::SynthesizeMouseEventFlags(event); 03188 03189 HandleDragEvent(MK_MBUTTON, nFlags, point, CLICKTYPE_DOUBLE); 03190 } 03191 03192 03193 03194 03195 /********************************************************************************************* 03196 > afx_msg void CCamView::OnRButtonDblClk(UINT32 nFlags, wxPoint point) 03197 03198 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 03199 Created: ages ago 03200 Inputs: Flags describing which buttons & keys were down when the message was sent; 03201 the coordinates of the mouse cursor 03202 Outputs: - 03203 Returns: - 03204 Purpose: Same as CCamView::OnLButtonDblClk(), bit for the right button. 03205 Errors: - 03206 Scope: Protected 03207 SeeAlso: class CRendWnd; CCamView::OnLButtonDblClk() 03208 03209 **********************************************************************************************/ 03210 03211 void CCamView::OnRButtonDblClk( wxMouseEvent &event ) 03212 { 03213 DontSkipNextMouse(); 03214 // If the event is not from the RenderWindow then skip it 03215 INT32 nID = event.GetId(); 03216 if (nID != WID_RENDERWINDOW) 03217 { 03218 // TRACEUSER("Gerry", _T("Ignoring mouse event in window %d\n"), nID); 03219 event.Skip(); 03220 return; 03221 } 03222 03223 wxPoint point = event.GetPosition(); 03224 UINT32 nFlags = ClickModifiers::SynthesizeMouseEventFlags(event); 03225 03226 HandleDragEvent(MK_RBUTTON, nFlags, point, CLICKTYPE_DOUBLE); 03227 } 03228 03229 03230 /********************************************************************************************* 03231 > afx_msg void CCamView::OnMouseWheel(UINT32 nFlags, short zDelta, wxPoint pt) 03232 03233 Author: Priestley (Xara Group Ltd) <camelotdev@xara.com> 03234 Created: 25/10/2000 03235 Purpose: 03236 Scope: Protected 03237 03238 **********************************************************************************************/ 03239 03240 void CCamView::OnMouseWheel( wxMouseEvent &event ) 03241 { 03242 DontSkipNextMouse(); 03243 HandleMouseWheelEvent( event ); 03244 } 03245 03246 /********************************************************************************************* 03247 > afx_msg void CCamView::OnMouseMove(UINT32 nFlags, wxPoint point) 03248 03249 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 03250 Created: ages ago 03251 Inputs: Flags describing which buttons & keys were down when the message was sent; 03252 the coordinates of the mouse cursor. 03253 Outputs: - 03254 Returns: - 03255 Purpose: Packages up OIL-layer mouse-move messages before passing them on to 03256 DocView::DragPointerMove(). If ScreenView is not in "drag mode" the event is 03257 passed to our DocView, which will forward it to the current tool. Otherwise, 03258 checks if a CLICKTYPE_DRAG message has been sent to the kernel, sending one if 03259 it hasn't (this smooths the difference between Windows and RISC OS, the former 03260 system providing little support for drag operations). 03261 Errors: - 03262 Scope: Protected 03263 SeeAlso: class CRendWnd; CCamView::HandleDragEvent(); DocView::DragPointerMove(); 03264 CCamView::GetClickMods(); CCamView::HandleDragScrolling(); 03265 DocView::OnMouseMove() 03266 **********************************************************************************************/ 03267 03268 void CCamView::OnMouseMove( wxMouseEvent &event ) 03269 { 03270 // Ignore if system is disabled 03271 if (CCamApp::IsDisabled()) 03272 return; // If the system is disabled, ignore 03273 03274 //TRACEUSER("Phil", _T("OnMouseMove %d %d %x\n"), event.LeftIsDown(), event.ShiftDown(), pCurrentDragOp); 03275 wxPoint point = event.GetPosition(); 03276 03277 // Only respond to real mouse move messages 03278 if (point == CurrentMousePos) 03279 return; 03280 03281 UINT32 nFlags = ClickModifiers::SynthesizeMouseEventFlags(event); 03282 03283 // Ignore mouse moves if we're not the foreground window. 03284 if (pDocView != DocView::GetSelected()) 03285 { 03286 return; 03287 } 03288 03289 StatusLine* pStatusLine=NULL; 03290 // flag that the StatusLine's mouse position field needs updating 03291 #ifndef RALPH 03292 03293 pStatusLine=GetApplication()->GetpStatusLine(); 03294 if (pStatusLine) 03295 pStatusLine->FlagMousePosNeedsUpdating(); 03296 #endif 03297 03298 SetCurrentStates(); 03299 03300 wxMouseState WXCMS = ::wxGetMouseState(); 03301 wxPoint CurrentMousePosition(WXCMS.GetX(), WXCMS.GetY()); 03302 // Make a number representing the current button and control key state - we don't use this for anything 03303 // other than seeing whether it has changed 03304 INT32 CurrentMouseState = 03305 (WXCMS.LeftDown() ?1:0) | 03306 (WXCMS.MiddleDown() ?2:0) | 03307 (WXCMS.RightDown() ?4:0) | 03308 (WXCMS.ControlDown()?8:0) | 03309 (WXCMS.ShiftDown() ?16:0) | 03310 (WXCMS.AltDown() ?32:0) | 03311 (WXCMS.MetaDown() ?64:0); 03312 #if 0 03313 TRACEUSER("amb", _T("CCamView:OnMouseMove XY (%d,%d) was (%d,%d) State %2x was %2x"), 03314 CurrentMousePosition.x, 03315 CurrentMousePosition.y, 03316 m_LastMousePosition.x, 03317 m_LastMousePosition.y, 03318 CurrentMouseState, 03319 m_LastMouseState); 03320 #endif 03321 INT32 CurrentTimestamp = event.GetTimestamp(); 03322 03323 BOOL SkipThis = FALSE; 03324 // wxWidgets compliant version of the PeekMessage code 03325 if (!DragKeepAccuracy && s_MouseMoveEliminationPeriod) 03326 { 03327 // What the windows version did was look ahead in the message queue for further 03328 // mouse moves. We don't have the luxury of that, so we do something slightly 03329 // different, which is that we look at where the mouse pointer has gone. 03330 // If it's moved, we know another mouse move event will be generated. So there 03331 // is the possibility of ignoring this one. We do this if the mouse BUTTON 03332 // state has not changed, the new mouse position is over the current window, 03333 // and some external event hasn't happened (normally a keypress) 03334 03335 // If this isn't a motion event or the button state has changed, don't skip this 03336 // event, or the next pure move 03337 if ((event.GetEventType() != wxEVT_MOTION) || (CurrentMouseState != m_LastMouseState)) 03338 { 03339 // Don't skip the next mouse event and don't skip this one 03340 m_CouldSkipNextMouse = FALSE; 03341 } 03342 else 03343 { 03344 m_CouldSkipNextMouse = TRUE; // next mouse move is a candidate for skipping 03345 03346 // we know the buttons are in the same position as before (and the modifiers) 03347 // and this is solely a motion event - a candidate to be skipped 03348 if (m_CouldSkipNextMouse && (CurrentMousePosition != m_LastMousePosition) /*&& (CurrentMousePosition != event.GetPosition())*/) 03349 { 03350 // OK, we know the mouse is moving. Insert a point every 20ms regardless 03351 if ((CurrentTimestamp - m_LastMouseUsedTimestamp) < s_MouseMoveEliminationPeriod) 03352 { 03353 SkipThis = TRUE; 03354 } 03355 } 03356 } 03357 } 03358 else 03359 { 03360 m_CouldSkipNextMouse = FALSE; 03361 } 03362 03363 m_LastMouseState = CurrentMouseState; 03364 m_LastMousePosition = CurrentMousePosition; 03365 03366 if (SkipThis) 03367 { 03368 return; 03369 } 03370 03371 m_LastMouseUsedTimestamp = CurrentTimestamp; 03372 03373 PORTNOTE("other","Remove PeekMessage related code") 03374 #ifndef EXCLUDE_FROM_XARALX 03375 // Only discard mouse move messages if the initiator of the drag has requested this. 03376 if (!DragKeepAccuracy) 03377 { 03378 // Due to problems with auto-repeat on modifier keys, we can lag a long way behind 03379 // with mouse messages, so we discard all except the most recent mouse move messages. 03380 // However we stop discarding mouse move messages if we come across any other mouse 03381 // messages such as button up/down events. 03382 MSG Msg; 03383 BOOL FoundMsg = FALSE; 03384 03385 for(;;) 03386 { 03387 // We have to test that the window handles match because of a bug in PeekMessage (we 03388 // get messages which aren't for the window we specified, strangely). 03389 03390 if (::PeekMessage(&Msg, m_hWnd, WM_MOUSEFIRST, WM_MOUSELAST, PM_NOREMOVE) && 03391 (m_hWnd == Msg.hwnd) && 03392 (Msg.message == WM_MOUSEMOVE)) 03393 { 03394 // Found a mouse move message on the queue... 03395 // Remember it then discard it. 03396 nFlags = (UINT32) Msg.wParam; 03397 03398 // Have to cast to INT8 so we get correct sign-extension. 03399 point.x = (INT8) LOWORD(Msg.lParam); 03400 point.y = (INT8) HIWORD(Msg.lParam); 03401 03402 // Discard the message 03403 PeekMessage(&Msg, m_hWnd, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE); 03404 FoundMsg = TRUE; 03405 } 03406 else 03407 { 03408 // Either: there are no messages, or it's not for our window, or it's a mouse 03409 // event which is not a mouse *move* event - whatever it is, stop looking 03410 // for mouse events. 03411 break; 03412 } 03413 } 03414 03415 // If we found any other mouse messages, use the data from the most recent one and 03416 // ignore the others. 03417 if (FoundMsg) 03418 { 03419 ENSURE(m_hWnd == Msg.hwnd, "Bad message in OnMouseMove"); 03420 nFlags = (UINT32) Msg.wParam; 03421 point.x = (INT8) LOWORD(Msg.lParam); 03422 point.y = (INT8) HIWORD(Msg.lParam); 03423 03424 03425 } 03426 } 03427 03428 // Slow mouse reponse due to key auto-repeat msgs? 03429 // 03430 // We could be experiencing delayed mouse move messages due to the message 03431 // queue getting flooded with key auto-repeat msgs. 03432 // 03433 // To overcome this, we remove all mouse move messages, keeping only the most 03434 // recent msg's coords & flags. 03435 // 03436 // Stripping the message cue in this way means we get less mouse moves to drag handlers, hence less accurate 03437 // mouse move data. But, as we only do this if we get an auto-repeated key stroke, accuracy should not be 03438 // a problem, even for the freehand tool. Freehand drags have two key modifiers (Alt for straught line and 03439 // Shift for rubbing out) that only require the latest mouse move event 03440 03441 MSG Msg; 03442 // Has there been a key msg during the mouse move? 03443 if (::PeekMessage(&Msg, m_hWnd, WM_KEYFIRST, WM_KEYLAST, PM_NOREMOVE)) 03444 { 03445 // Have a look at the key msg (use KeyPressSysMsg to turn the msg into a system-independant format) 03446 KeyPressSysMsg KeySysMsg(&Msg); 03447 03448 // Is the key msg an auto-repeated key press (i.e. previously down)? 03449 if (KeySysMsg.IsValid() && KeySysMsg.PrevDown) 03450 { 03451 // Auto repeat key msg found, so get the latest mouse move msg 03452 // Note: We don't remove the msg from the queue, it may need to be processed elsewhere (e.g. button-ups) 03453 while (::PeekMessage(&Msg, m_hWnd, WM_MOUSEFIRST, WM_MOUSELAST, PM_NOREMOVE)) 03454 { 03455 // Is the mouse msg a mouse move msgs? 03456 if (Msg.message == WM_MOUSEMOVE) 03457 { 03458 // Found a mouse move message on the queue so remember it 03459 nFlags = (UINT32) Msg.wParam; 03460 03461 // Have to cast to INT8 so we get correct sign-extension. 03462 point.x = (INT8) LOWORD(Msg.lParam); 03463 point.y = (INT8) HIWORD(Msg.lParam); 03464 03465 // Remove the mouse move msg, and get the next mouse msg in the queue 03466 ::PeekMessage(&Msg, m_hWnd, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE); 03467 } 03468 else 03469 { 03470 // We have got a mouse msg that's not a mouse move msg, so break out of 'while' loop 03471 // This could be a button-up msg, in which case we should stop looking for 03472 // mouse moves as they may be irrelevent to the current drag 03473 break; 03474 } 03475 } 03476 } 03477 } 03478 #endif 03479 03480 #if !defined(EXCLUDE_FROM_RALPH) && !defined(EXCLUDE_FROM_XARALX) 03481 // WEBSTER - markn 25/4/97 03482 // No pen stuff required in Webster 03483 // Taken out by vector stroking code Neville 2/10/97 03484 #ifdef VECTOR_STROKING 03485 03486 // Now check the Mouse Message to see if it has any pressure information 03487 (Camelot.GetPressurePen())->CheckMouseMessage(WM_MOUSEMOVE, point); 03488 #endif // VECTOR_STROKING 03489 #endif 03490 03491 // Set the DocView (and Document) 03492 // pDocView->SetCurrent(); 03493 03494 03495 // Find out which buttons/keys are down. 03496 GetClickMods(event, &LastClickMods); 03497 03498 // Are we dragging at the moment? 03499 if (pCurrentDragOp) 03500 { 03501 // Yes, but just check that the drag isn't "paused" while we do an OLE drag outside the window 03502 if (GetRenderWindow()->GetCapture() == GetRenderWindow()) 03503 { 03504 // Check if we need to scroll this view. 03505 HandleDragScrolling(point); 03506 03507 WinCoord wpoint(point.x, point.y); 03508 OilCoord CurDragOilPoint = wpoint.ToOil(pDocView, TRUE); 03509 // TRACEUSER("Gerry", _T("DragMove (%d, %d)\n"), (INT32)CurDragOilPoint.x, (INT32)CurDragOilPoint.y); 03510 // Send an on-going drag event to the kernel. 03511 pDocView->DragPointerMove(pCurrentDragOp, CurDragOilPoint, LastClickMods); 03512 } 03513 } 03514 else 03515 { 03516 // We are not dragging at the moment, but are we about to start a drag? If the 03517 // last mouse event was a single click, the same buttons are down, and the mouse 03518 // has either moved (3 or more), then a drag is beginning. 03519 INT32 dx = point.x - LastClickPoint.x; 03520 INT32 dy = point.y - LastClickPoint.y; 03521 INT32 dz2 = (dx * dx) + (dy * dy); 03522 if ((nFlags & FirstClickButton) && (dz2 >= (DragLatency * DragLatency))) 03523 { 03524 // Inform the kernel that a drag is starting. 03525 HandleDragEvent(FirstClickButton, nFlags, LastClickPoint, CLICKTYPE_DRAG); 03526 } 03527 else 03528 { 03529 WinCoord wpoint(point.x, point.y); 03530 // We are not dragging, just moving the mouse around, so pass the position 03531 // of the mouse to the tool, giving it an opportunity to set the cursor etc. 03532 pDocView->OnMouseMove( wpoint.ToOil(pDocView, TRUE), LastClickMods); 03533 } 03534 } 03535 03536 // Remember the last position of the mouse passed on to the kernel. The position 03537 // passed on any subsequent DragPointerIdle events must be the same as this! 03538 CurrentMousePos = point; 03539 03540 #if !defined(EXCLUDE_FROM_RALPH) 03541 // if status line has not already been updated by someone calling CSnap::Snap(), call 03542 // CSnap::Snap(), snapping to grid only, to update status line (and ruler mouse followers) 03543 if (pStatusLine && pStatusLine->MousePosNeedsUpdating()) 03544 { 03545 OilCoord OilPos=((WinCoord*)&point)->ToOil(pDocView, TRUE); 03546 DocCoord DocPos(0,0); 03547 Spread* pSpread=pDocView->OilToSpreadCoord(OilPos,&DocPos); 03548 if (pSpread) 03549 pDocView->Snap(pSpread,&DocPos,TRUE,TRUE); 03550 } 03551 #endif 03552 } 03553 03554 /********************************************************************************************* 03555 > void CCamView::OnSetCursor(wxSetCursorEvent& event) 03556 03557 Author: Luke_Hart (Xara Group Ltd) <camelotdev@xara.com> 03558 Created: 08/02/06 03559 Inputs: The event. 03560 Outputs: - 03561 Returns: - 03562 Purpose: Eat the cursor update requests to stop anyone else playing with them, this is 03563 needed on MSW or the cursor reverts to the normal arrow. 03564 Errors: - 03565 Scope: Protected 03566 SeeAlso: 03567 03568 **********************************************************************************************/ 03569 03570 void CCamView::OnSetCursor( wxSetCursorEvent& event ) 03571 { 03572 // TRACEUSER("Gerry", _T("CCamView::OnSetCursor")); 03573 #if !defined(EXCLUDE_FROM_XARALX) 03574 // Child windows assume responsibility for setting their own cursor. 03575 if( event.GetEventObject() == RenderWindow ) 03576 { 03577 #endif 03578 // Ignore if system is disabled 03579 if (CCamApp::IsDisabled()) 03580 return; // If the system is disabled, ignore 03581 03582 SetCurrentStates(); 03583 03584 Cursor* pCursor = NULL; 03585 03586 if (IsTopmost() || 03587 CursorStack::GIsActive(Cursor::Busy) || 03588 CursorStack::GIsActive(Cursor::Progress)) 03589 { 03590 // The view window is active, or the machine is busy on a slow task, so we must show 03591 // the cursor on the top of the cursor stack. 03592 pCursor = CursorStack::GetActive(); 03593 // TRACEUSER("Gerry", _T("Setting CursorStack::GetActive (0x%08x)"), pCursor); 03594 } 03595 else 03596 { 03597 // This view is overlapped and the machine isn't busy, so show a normal arrow cursor. 03598 // TRACEUSER("Gerry", _T("Setting Cursor::Arrow")); 03599 pCursor = Cursor::Arrow; 03600 } 03601 03602 if( NULL != pCursor ) 03603 { 03604 // TRACEUSER("Gerry", _T("Setting event cursor to 0x%08x"), pCursor->Handle()); 03605 event.SetCursor( *(pCursor->Handle()) ); 03606 } 03607 03608 #if !defined(EXCLUDE_FROM_XARALX) 03609 } 03610 else 03611 if( event.GetEventObject() == Corner ) 03612 Corner->OnSetCursor( event ); 03613 #endif 03614 } 03615 03616 03617 /********************************************************************************************* 03618 > void CCamView::OnScroll(wxSizeEvent &event) 03619 03620 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 03621 Created: ages ago 03622 Inputs: The wxScrollEvent object 03623 Outputs: - 03624 Returns: - 03625 Purpose: Handles all the scroll events. 03626 Errors: - 03627 SeeAlso: 03628 03629 03630 **********************************************************************************************/ 03631 03632 void CCamView::OnScroll(wxScrollEvent &event) 03633 { 03634 // TRACEUSER("Gerry", _T("CCamView::OnScroll Orient = %d Position = %d\n"), event.GetOrientation(), event.GetPosition()); 03635 03636 wxEventType Type = event.GetEventType(); 03637 03638 /* if (Type == wxEVT_SCROLL_CHANGED) 03639 { 03640 TRACEUSER("Gerry", _T("wxEVT_SCROLL_CHANGED\n")); 03641 if (event.GetOrientation() == wxHORIZONTAL) 03642 { 03643 TRACEUSER("Gerry", _T("Horizontal = %d\n"), event.GetPosition()); 03644 } 03645 else 03646 { 03647 TRACEUSER("Gerry", _T("Vertical = %d\n"), event.GetPosition()); 03648 } 03649 }*/ 03650 03651 if (Type == wxEVT_SCROLL_LINEUP) 03652 { 03653 // TRACEUSER("Gerry", _T("wxEVT_SCROLL_LINEUP\n")); 03654 CWinScroller* pBar = NULL; 03655 if (event.GetOrientation() == wxHORIZONTAL) 03656 pBar = HScrollBar; 03657 else 03658 pBar = VScrollBar; 03659 if (pBar) 03660 pBar->SetThumbPosition(pBar->GetThumbPosition() - 20); 03661 } 03662 else if (Type == wxEVT_SCROLL_LINEDOWN) 03663 { 03664 // TRACEUSER("Gerry", _T("wxEVT_SCROLL_LINEDOWN\n")); 03665 CWinScroller* pBar = NULL; 03666 if (event.GetOrientation() == wxHORIZONTAL) 03667 pBar = HScrollBar; 03668 else 03669 pBar = VScrollBar; 03670 if (pBar) 03671 pBar->SetThumbPosition(pBar->GetThumbPosition() + 20); 03672 } 03673 03674 // TRACEUSER("Gerry", _T("Pos = (%d, %d)\n"), HPos, VPos); 03675 SetCurrentStates(); 03676 if (Status && fSetupDone) 03677 { 03678 WorkCoord temp; 03679 GetScrollOffset(&temp); 03680 Status->SetScrollPos(temp); 03681 ScrollTo(temp); 03682 } 03683 } 03684 03685 03686 /********************************************************************************************* 03687 > afx_msg void CCamView::OnSize(wxSizeEvent &event) 03688 03689 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 03690 Created: ages ago 03691 Inputs: A flag indicating whether the window is maximised, minimised 03692 etc., the width and height of the ScreenView client area. 03693 Outputs: - 03694 Returns: - 03695 Purpose: Resizes and repositions all child windows to fit the new size 03696 of the ScreenView. Updates the ViewState object with the 03697 size and position of the view, in an OS-independent manner. 03698 Resets the scroller's page and line size, and forces an 03699 immediate redraw of all affected windows. 03700 Errors: - 03701 Scope: Protected 03702 SeeAlso: CScroller::CalcPosFromParentClient(); CScroller::SetPageSize(); 03703 CScroller::SetLineSize(); class CRendWnd; class CScrollerCorner; 03704 struct ViewState; DocView::ViewStateChanged() 03705 03706 03707 **********************************************************************************************/ 03708 03709 void CCamView::OnSize( wxSizeEvent &event ) 03710 { 03711 TRACEUSER("Gerry", _T("CCamView::OnSize(%d, %d)\n"), event.m_size.x, event.m_size.y); 03712 03713 // This is called early, so if pDocView is null do nothing 03714 if( NULL == pDocView ) 03715 return; 03716 03717 SetCurrentStates(); 03718 03719 Document* pCurDoc = Document::GetCurrent(); 03720 DocView* pCurView = DocView::GetCurrent(); 03721 03722 wxSize NewSize( event.GetSize() ); 03723 // TRACEUSER("Gerry", _T("CCamView::OnSize Size = (%d, %d)\n"), NewSize.x, NewSize.y); 03724 03725 wxRect ClientRect = m_pFrame->GetClientRect(); 03726 wxRect RenderRect = ClientRect; 03727 03728 // Check for irrelevant or potty messages. 03729 if (NewSize.x <= 0 || NewSize.y <= 0) 03730 { 03731 TRACE(_T("Bad size in CCamView::OnSize(%d, %d)\n"), NewSize.x, NewSize.y); 03732 return; 03733 } 03734 03735 if (Status->RulersVisible) 03736 { 03737 // Get size of rulers and shove the left and top of the RenderRect in 03738 WinRect hRect, vRect, oRect; 03739 03740 HRuler->CalcPosFromParentClient(&hRect); 03741 HRuler->SetSize(hRect); 03742 HRuler->PositionLegend(); 03743 03744 RenderRect.y += hRect.GetHeight(); 03745 RenderRect.height -= hRect.GetHeight(); 03746 03747 VRuler->CalcPosFromParentClient(&vRect); 03748 VRuler->SetSize(vRect); 03749 03750 RenderRect.x += vRect.GetWidth(); 03751 RenderRect.width -= vRect.GetWidth(); 03752 03753 OGadget->CalcPosFromParentClient(&oRect); 03754 OGadget->SetSize(oRect); 03755 } 03756 03757 if (Status->ScrollersVisible) 03758 { 03759 // Resize and reposition the proportional scrollers. 03760 03761 wxSize HScrSize; 03762 HScrollBar->GetBestSize(&HScrSize.x, &HScrSize.y); 03763 // TRACEUSER("Gerry", _T("HScroll BestSize = (%d, %d)\n"), HScrSize.x, HScrSize.y); 03764 wxSize VScrSize; 03765 VScrollBar->GetBestSize(&VScrSize.x, &VScrSize.y); 03766 // TRACEUSER("Gerry", _T("VScroll BestSize = (%d, %d)\n"), VScrSize.x, VScrSize.y); 03767 03768 wxRect HScrRect(RenderRect.x, ClientRect.height - HScrSize.y, RenderRect.width - VScrSize.x, HScrSize.y); 03769 // TRACEUSER("Gerry", _T("HScrRect = (%d, %d) [%d, %d]\n"), HScrRect.x, HScrRect.y, HScrRect.width, HScrRect.height); 03770 HScrollBar->SetSize(HScrRect); 03771 03772 wxRect VScrRect(ClientRect.width - VScrSize.x, RenderRect.y, VScrSize.x, RenderRect.height - HScrSize.y); 03773 // TRACEUSER("Gerry", _T("VScrRect = (%d, %d) [%d, %d]\n"), VScrRect.x, VScrRect.y, VScrRect.width, VScrRect.height); 03774 VScrollBar->SetSize(VScrRect); 03775 03776 // Reposition the corner window at the bottom-right. 03777 wxRect CornerRect(VScrRect.x, HScrRect.y, VScrRect.width, HScrRect.height); 03778 // Corner->SetSize(CornerRect); 03779 03780 // Adjust the RenderRect to account for the scroll bars 03781 RenderRect.width -= VScrSize.x; 03782 RenderRect.height -= HScrSize.y; 03783 ScrollBarSize = max(VScrSize.x, HScrSize.y); 03784 } 03785 03786 wxRect OldRect = RenderWindow->GetRect(); 03787 // TRACEUSER("Gerry", _T("OldRect = (%d, %d) [%d, %d]\n"), OldRect.x, OldRect.y, OldRect.width, OldRect.height); 03788 03789 // Resize/reposition the rendering window. 03790 CurrentSize = RenderRect; 03791 // TRACEUSER("Gerry", _T("RenderRect = (%d, %d) [%d, %d]\n"), RenderRect.x, RenderRect.y, RenderRect.width, RenderRect.height); 03792 RenderWindow->SetSize(RenderRect); 03793 03794 // Update the rest of the window placement information. 03795 UpdateViewPosition(); 03796 03797 // Calculate the work area, page & line sizes etc etc. 03798 // FIXED16 PixelWidth, PixelHeight; 03799 // pDocView->GetPixelSize(&PixelWidth, &PixelHeight); 03800 03801 // XLONG x1 = CurrentSize.GetWidth() * PixelWidth; 03802 // XLONG x2 = CurrentSize.GetHeight() * PixelHeight; 03803 // HScrollBar->SetPageSize(x1); 03804 // VScrollBar->SetPageSize(x2); 03805 // HScrollBar->SetLineSize(x1 / xlong(10) + xlong(1)); 03806 // VScrollBar->SetLineSize(x2 / xlong(10) + xlong(1)); 03807 03808 SetWorkAreaExtent(Status->WorkAreaExtent, FALSE); 03809 03810 // Make sure the scroll offsets are valid - if we resize the bottom of the window 03811 // when at the extreme bottom of the view, then the scroll offsets should be 03812 // changed - we use the scrollers' own integrity checks to do this automatically. 03813 // Don't do this until the setup flag is TRUE, so we don't overwrite scroll offsets 03814 // that have been reloaded. 03815 if (fSetupDone) 03816 { 03817 TRACEUSER("Gerry", _T("fSetupDone so setting scroll offsets\n")); 03818 WorkCoord CurrScrollPos; 03819 GetScrollOffset(&CurrScrollPos); 03820 SetScrollOffset(CurrScrollPos, TRUE); 03821 } 03822 03823 // Inform the associated DocView object that something has happened. 03824 pDocView->ViewStateChanged(); 03825 pCurDoc->SetCurrent(); 03826 pCurView->SetCurrent(); 03827 } 03828 03829 03830 /********************************************************************************************* 03831 > void CCamView::OnDragIdle(wxTimerEvent& event) 03832 03833 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 03834 Created: ages ago 03835 Inputs: The elapsed timer's numeric identifier (not used). 03836 Outputs: - 03837 Returns: - 03838 Purpose: Sends DragPointerIdle "events" to the kernel, when dragging. As Windows 03839 doesn't support such "idle" messages, the OIL drag system sets up a timer 03840 when a drag starts, and sends idle messages every time the timer elapses, 03841 until the drag is finished. 03842 Errors: - 03843 Scope: Protected 03844 SeeAlso: CCamView::HandleDragEvent(); DocView::DragPointerMove(); 03845 CCamView::GetClickMods(); 03846 03847 **********************************************************************************************/ 03848 03849 void CCamView::OnDragIdle(wxTimerEvent& event) 03850 { 03851 DontSkipNextMouse(); 03852 // Ignore if system is disabled 03853 if (CCamApp::IsDisabled()) 03854 return; // If the system is disabled, ignore 03855 03856 // This window should never get a timer event that does not occur between calls to 03857 // StartDrag() and EndDrag(). 03858 // ENSURE(pCurrentDragOp != 0, "CCamView::StartDrag: pCurrentDragOp is null"); 03859 03860 // Find out which keys/buttons are being held down at the moment. The mouse buttons 03861 // are more difficult, as they may have been swapped. 03862 UINT32 nFlags = ClickModifiers::SynthesizeMouseEventFlags(); 03863 03864 SetCurrentStates(); 03865 03866 if (pCurrentDragOp == NULL) 03867 { 03868 // We are not dragging at the moment, so check for a time-out condition to 03869 // start a drag: 03870 // If a mouse button is down, and the timer has expired, then start a drag. 03871 if (LastClickType!=CLICKTYPE_NONE 03872 && (nFlags & (MK_LBUTTON|MK_MBUTTON|MK_RBUTTON)) 03873 && DragTimer.Elapsed(DragDelay) 03874 && GetCurrentMousePos(NULL) 03875 ) 03876 { 03877 // Inform the kernel that a drag is starting. 03878 HandleDragEvent(FirstClickButton, nFlags, LastClickPoint, CLICKTYPE_DRAG); 03879 } 03880 } 03881 else 03882 { 03883 // If we're doing an OLE drag and drop operation, then our DragOperation is still 03884 // active, but we have lost the Mouse Capture, so we should not update anything. 03885 // If the user drags back into our view window, the OLE drag will be shut down 03886 // and we will be given back our mouse capture so we can continue as if nothing 03887 // had happened. This just stops us scrolling while the OLE system is in charge! 03888 if (GetRenderWindow()->GetCapture() == GetRenderWindow()) 03889 { 03890 WorkCoord OldScrollOffset; 03891 GetScrollOffset(&OldScrollOffset); 03892 03893 // Check if we need to scroll the screen . . . 03894 HandleDragScrolling(CurrentMousePos); 03895 03896 // We need to know if we have scrolled 03897 WorkCoord NewScrollOffset; 03898 GetScrollOffset(&NewScrollOffset); 03899 BOOL bScrolled = (NewScrollOffset.x != OldScrollOffset.x) || (NewScrollOffset.y != OldScrollOffset.y); 03900 03901 // The above call may have aborted the current DragOp, so we must check if it is NULL 03902 if (pCurrentDragOp != NULL) 03903 { 03904 // Now "fake" a mouse event for the kernel . . . 03905 LastClickMods = ClickModifiers::GetClickModifiers(nFlags); 03906 OilCoord CurDragOilPoint = ((WinCoord*)&CurrentMousePos)->ToOil(pDocView, TRUE); 03907 if (bScrolled) 03908 { 03909 // TRACEUSER("Gerry", _T("DragMove (%d, %d)\n"), (INT32)CurDragOilPoint.x, (INT32)CurDragOilPoint.y); 03910 pDocView->DragPointerMove(pCurrentDragOp, CurDragOilPoint, LastClickMods); 03911 } 03912 else 03913 { 03914 // TRACEUSER("Gerry", _T("DragIdle (%d, %d)\n"), (INT32)CurDragOilPoint.x, (INT32)CurDragOilPoint.y); 03915 pDocView->DragPointerIdle(pCurrentDragOp, CurDragOilPoint, LastClickMods); 03916 } 03917 } 03918 } 03919 else 03920 { 03921 // We don't own the capture - but if the user was OLE dragging and has dragged back into our 03922 // view window, then the OLE drag will have been cancelled, and we need to recapture the 03923 // mouse so that we can continue processing the drag as if nothing happened. Our OLE DropSource 03924 // will set our OLERecaptureMouse flag if it cancels itself and wishes us to continue... 03925 if (OLERecaptureMouse) 03926 { 03927 GetRenderWindow()->CaptureMouse(); 03928 OLERecaptureMouse = FALSE; // Only capture it back once! 03929 } 03930 } 03931 } 03932 } 03933 03934 /********************************************************************************************* 03935 > void CCamView::ScrollTo(const WorkCoord& offset) 03936 03937 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 03938 Created: ages ago 03939 Inputs: The position, in WorkCoords, that the top-left corner of the view is to 03940 move to. 03941 Outputs: - 03942 Returns: - 03943 Purpose: Scroll the client area of the window to the specified position. The offset 03944 must be converted to OS coordinates before being passed to Windows. If the 03945 new position of the view does not overlap the old position then the client 03946 area is completely redrawn. Otherwise, the Windows USER module is called 03947 to scroll the window. 03948 Errors: - 03949 Scope: Private 03950 SeeAlso: CCamView::SetScrollPos() 03951 03952 **********************************************************************************************/ 03953 03954 void CCamView::ScrollTo(const WorkCoord& offset) 03955 { 03956 // TRACEUSER("Gerry", _T("CCamView::ScrollTo(%d, %d)\n"), (INT32)offset.x, (INT32)offset.y); 03957 // Calculate the difference between where we are and where we want to be. Notice 03958 // the asymmetry in the calculations, to account for the Windows coordinate origin 03959 // being in the top-left, not the bottom-left. 03960 FIXED16 PixelWidth, PixelHeight; 03961 pDocView->GetPixelSize(&PixelWidth, &PixelHeight); 03962 INT32 dx = ((offset.x - OldOffset.x) / PixelWidth.MakeLong() ); 03963 INT32 dy = ((OldOffset.y - offset.y) / PixelHeight.MakeLong() ); 03964 if (dx == 0 && dy == 0) 03965 { 03966 // TRACEUSER("Gerry", _T("No change\n")); 03967 return; 03968 } 03969 03970 // Scroll part of, or redraw the whole of, the client area. 03971 if (Abs(dx) >= CurrentSize.GetRight() || Abs(dy) >= CurrentSize.GetBottom() ) 03972 { 03973 // TRACEUSER("Gerry", _T("Full refresh\n")); 03974 GetRenderWindow()->Refresh(true); 03975 } 03976 else 03977 { 03978 // TRACEUSER("Gerry", _T("ScrollWindow(%d, %d)\n"), -dx, -dy); 03979 GetRenderWindow()->ScrollWindow(-dx, -dy); 03980 } 03981 03982 #if !defined(EXCLUDE_FROM_RALPH) 03983 if (Status->RulersVisible) 03984 { 03985 if(HRuler) 03986 HRuler->ScrollRuler(-dx); 03987 if(VRuler) 03988 VRuler->ScrollRuler(-dy); 03989 03990 } 03991 #endif 03992 03993 // Remember this scroll offset, which corresponds to what will be drawn on the screen, 03994 // and force an immediate repaint of the invalid area. 03995 OldOffset = offset; 03996 GetRenderWindow()->Update(); 03997 // TRACEUSER("Gerry", _T("Done update\n")); 03998 03999 #if !defined(EXCLUDE_FROM_RALPH) // && !defined(EXCLUDE_FROM_XARALX) 04000 // Make sure that the system will update the state of gadgets after this, some of 04001 // which may now be "greyed" because what they apply to is no longer visible etc. 04002 // This is the best place to put this, as all scroll requests, whether they come 04003 // from the user or are internally generated, go through this function. 04004 DialogBarOp::SetSystemStateChanged(TRUE); 04005 #endif 04006 } 04007 04008 04009 04010 /******************************************************************************************** 04011 > static void CCamView::wxPoint2Coord(const wxPoint& point, Coord* pcoord) 04012 04013 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 04014 Created: 7/4/94 04015 Inputs: - 04016 Outputs: - 04017 Returns: - 04018 Purpose: Converts a wxPoint to a kernel Coord. 04019 Errors: - 04020 SeeAlso: - 04021 ********************************************************************************************/ 04022 04023 void CCamView::wxPoint2Coord(const wxPoint& point, Coord* pcoord) 04024 { 04025 pcoord->x = point.x; 04026 pcoord->y = point.y; 04027 } 04028 04029 04030 04031 /******************************************************************************************** 04032 > static void CCamView::Coord2wxPoint(const Coord& coord, wxPoint* ppoint) 04033 04034 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 04035 Created: 7/4/94 04036 Inputs: - 04037 Outputs: - 04038 Returns: - 04039 Purpose: Converts a kernel Coord to a wxPoint. 04040 Errors: - 04041 SeeAlso: - 04042 ********************************************************************************************/ 04043 04044 void CCamView::Coord2wxPoint(const Coord& coord, wxPoint* ppoint) 04045 { 04046 ppoint->x = (INT32) coord.x; 04047 ppoint->y = (INT32) coord.y; 04048 } 04049 04050 04051 04052 /******************************************************************************************** 04053 > static void CCamView::wxRect2Rect(const wxRect& rect, Rect* pkrect) 04054 04055 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 04056 Created: 7/4/94 04057 Inputs: - 04058 Outputs: - 04059 Returns: - 04060 Purpose: Converts a wxRect into a kernel Rect. 04061 Errors: - 04062 SeeAlso: - 04063 ********************************************************************************************/ 04064 04065 void CCamView::wxRect2Rect(const wxRect& rect, Rect* pkrect) 04066 { 04067 pkrect->lo.x = rect.GetLeft(); 04068 pkrect->lo.y = rect.GetTop(); 04069 pkrect->hi.x = rect.GetLeft() + rect.GetWidth(); 04070 pkrect->hi.y = rect.GetTop() + rect.GetHeight(); 04071 } 04072 04073 04074 /******************************************************************************************** 04075 > static void CCamView::Rect2wxRect(const Rect& krect, wxRect* prect) 04076 04077 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 04078 Created: 7/4/94 04079 Inputs: - 04080 Outputs: - 04081 Returns: - 04082 Purpose: Converts a kernel Rect into a wxRect. 04083 Errors: - 04084 SeeAlso: - 04085 ********************************************************************************************/ 04086 04087 void CCamView::Rect2wxRect(const Rect& krect, wxRect* prect) 04088 { 04089 prect->x = (INT32) krect.lo.x; 04090 prect->y = (INT32) krect.lo.y; 04091 prect->width = (INT32) krect.Width(); 04092 prect->height = (INT32) krect.Height(); 04093 } 04094 04095 04096 04097 /******************************************************************************************** 04098 > void CCamView::HandleDragEvent(UINT32 Button, UINT32 nFlags, wxPoint point, ClickType t) const 04099 > void CCamView::HandleDragEvent(UINT32 Button, ClickModifiers clickmods, wxPoint point, ClickType t) 04100 04101 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 04102 Created: ages ago 04103 Inputs: Button - the actual button being pressed for a click/double click event. 04104 nFlags - The mouse button flags 04105 clickmods - The kernel abstraction of the modifiers 04106 point - the coordinate of the mouse cursor 04107 t - the kind of mouse event (button up/down, move, drag start/finish etc.) 04108 Outputs: - 04109 Returns: - 04110 Purpose: Gathers together Windows information about a mouse event and passes it on to 04111 the kernel, by calling DocView::OnClick() 04112 HandleDragEvent needs to be called from OnTimer code so rather than 04113 synthesizing a wxMouseEvent object this function has been left taking 04114 non-wx params 04115 Errors: - 04116 Scope: Private 04117 SeeAlso: CCamView::GetClickMods(); CCamView::OnLButtonDown(); CCamView::OnRButtonDown() 04118 DocView::OnClick() 04119 04120 ********************************************************************************************/ 04121 04122 /******************************************************************************************** 04123 04124 Technical notes (by Tim): 04125 04126 The Button is parameter is necessary, because sometimes when we get the *first* button 04127 down event, nFlags has more than one mouse button bit set. This only happens when you 04128 rampantly click buttons very quickly but nevertheless we *do* need to know which button 04129 was pressed, otherwise we never release the drag event and we end up with button-up-drag 04130 city. 04131 04132 I assume this is due to some latency in Windows, e.g., it gets a button down event, and 04133 while preparing it goes and reads the mouse button state and meanwhile another button has 04134 been pressed so we get a button down event with nFlags indicating more than one button 04135 is down. 04136 04137 ********************************************************************************************/ 04138 04139 void CCamView::HandleDragEvent(UINT32 Button, UINT32 nFlags, wxPoint point, ClickType t) 04140 { 04141 // Find out which buttons etc are down. 04142 ClickModifiers clickmods = ClickModifiers::GetClickModifiers(nFlags); 04143 04144 HandleDragEvent(Button, clickmods, point, t); 04145 } 04146 04147 void CCamView::HandleDragEvent(UINT32 Button, ClickModifiers clickmods, wxPoint point, ClickType t) 04148 { 04149 if (DocView::GetSelected() != pDocView) 04150 { 04151 // TRACEUSER( "JustinF", _T("Ignored drag-event cos not in the selected view\n")); 04152 // If selected doc is null, let's select it anyway. 04153 if (DocView::GetSelected() == NULL) 04154 { 04155 // We're in a weird state that should never happen but does - a document 04156 // has the focus, but isn't selected 04157 Document* pKDoc =NULL; 04158 if(pDocView) 04159 pKDoc = pDocView->GetDoc(); 04160 04161 if (pKDoc) 04162 { 04163 Document::SetSelectedViewAndSpread(pKDoc, pDocView, NULL); 04164 } 04165 04166 } 04167 return; 04168 } 04169 04170 SetCurrentStates(); 04171 04172 // Find out which buttons etc are down. 04173 LastClickMods = clickmods; 04174 04175 // If it's the first single click, then reset the drag delay timer, and ask for a 04176 // Windows timer. 04177 if (((t == CLICKTYPE_SINGLE) || (t == CLICKTYPE_DOUBLE)) && 04178 (FirstClickButton == 0)) 04179 { 04180 // Remember this event. 04181 LastClickPoint = point; 04182 LastClickType = t; 04183 LastClickButton = Button; 04184 FirstClickButton = Button; 04185 DragTimer.Sample(); 04186 04187 #if (_OLE_VER >= 0x200) 04188 // The user's doing something so don't update any container docs 04189 CCamDoc::ResetContainerUpdateTimer(); 04190 #endif 04191 04192 // Ask the system for a timer. 04193 // The timer is used to generate DragPointerIdle events, which are not directly 04194 // supported by Windows. 04195 UINT32 rate = 100; 04196 PORTNOTE("other","Removed reading of keyboard autorepeat rate") 04197 #ifndef EXCLUDE_FROM_XARALX 04198 ::SystemParametersInfo(SPI_GETKEYBOARDSPEED, 0, &rate, 0); 04199 #endif 04200 04201 m_DragIdleTimer.Start(rate); 04202 } 04203 04204 if (DragOpInvoke) 04205 { 04206 OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(DragOpToken); 04207 04208 ERROR3IF_PF(pOpDesc == NULL,("FindOpDescriptor(%s) failed",(TCHAR*)DragOpToken)); 04209 04210 if (pOpDesc != NULL) 04211 pOpDesc->Invoke(pDragOpParam); 04212 04213 // Reset the vars ready for the next call to InvokeDragOp() 04214 DragOpInvoke = FALSE; 04215 pDragOpParam = NULL; 04216 } 04217 else 04218 { 04219 // Convert the click position to OIL coordinates before passing to the kernel. 04220 // pDocView->SetCurrent(); 04221 WinCoord wpoint(point.x, point.y); 04222 pDocView->OnClick( ( (WinCoord *)&point )->ToOil(pDocView, TRUE), t, LastClickMods); 04223 } 04224 } 04225 04226 04227 04228 /******************************************************************************************** 04229 > BOOL CCamView::HandleMouseWheelEvent(UINT32 nFlags, short zDelta, wxPoint pt) 04230 Author: Priestley (Xara Group Ltd) <camelotdev@xara.com> 04231 Created: 25/10/2000 04232 Purpose: Handle MouseWheel for Scroll document and Zoom operations 04233 Also dispatches a message to the Gallery the mouse is over, if any... 04234 Inputs: nFlags - The mouse flags 04235 zDelta - movement of the mousewheel 04236 pt - the coordinate of the mouse cursor 04237 ********************************************************************************************/ 04238 04239 BOOL CCamView::HandleMouseWheelEvent( wxMouseEvent &event ) 04240 { 04241 // Reasons Why This Is Done As It Is... 04242 // ************************************ 04243 // 04244 // The WM_MOUSEWHEEL message is only ever sent to the window with focus. Galleries 04245 // never have the focus, even though they show they have (their windows are highlighted) 04246 // as this is done using rendering onto a blank window (as is their grey-ing out) 04247 // As a result of this, a Gallery is never sent a WM_MOUSEWHEEL message. 04248 // We therefore need to trap the message (here is as good a place as any) and check if the 04249 // user was actually over a gallery... 04250 // Finding out if they are over a Gallery SHOULD have been quite easy (eg WindowFromPoint()) 04251 // EXCEPT that we don't create the Galleries in any sensible manner, thus they aren't 04252 // children of the current window - they are children of the Program Manager - sensible... 04253 // So, when we ask for the appropriate HWND it returns a nonsense value... Anyhow, the 04254 // following code gets around this and gives us the real HWND of the Gallery underneath the 04255 // mouse, OR returns NULL if no bar was found. 04256 // In the case where we get the Gallery HWND, we dispatch a message to scroll up/down according 04257 // to mousewheel delta. In the case where we have no HWND we check if the mouse lies within the 04258 // currently selected view and if it does, then scroll appropriately. 04259 // If anyone can see an easier way, then let me know!!! 04260 // Matt 1/11/00 04261 04262 INT32 zDelta = event.GetWheelRotation(); 04263 INT32 zStep = event.GetWheelDelta(); 04264 04265 PORTNOTETRACE("other","CCamView::HandleMouseWheelEvent - removed gallery bits"); 04266 #ifndef EXCLUDE_FROM_XARALX 04267 // We need to know if the mouse pointer is over a Gallery, and if it is what the 04268 // HWND of that Gallery is, so that I can send it a scroll message... 04269 HWND OverBar = GetMainFrame()->IsScreenPointInBar(pt); 04270 04271 if (OverBar) 04272 { 04273 if (zDelta < 0) 04274 { 04275 BROADCAST_TO_CLASS(DialogMsg(OverBar, DIM_MOUSEWHEEL_DOWN, 256), DialogOp); 04276 } 04277 else 04278 { 04279 BROADCAST_TO_CLASS(DialogMsg(OverBar, DIM_MOUSEWHEEL_UP, 256), DialogOp); 04280 } 04281 } 04282 else 04283 #endif 04284 { 04285 //Preliminary Checks... 04286 if (DocView::GetSelected() != pDocView) 04287 { 04288 // If selected doc is null, let's select it anyway. 04289 if (DocView::GetSelected() == NULL) 04290 { 04291 // We're in a weird state that should never happen but does - a document 04292 // has the focus, but isn't selected 04293 Document* pKDoc =NULL; 04294 if(pDocView) 04295 { 04296 pKDoc = pDocView->GetDoc(); 04297 } 04298 04299 if (pKDoc) 04300 { 04301 Document::SetSelectedViewAndSpread(pKDoc, pDocView, NULL); 04302 } 04303 04304 } 04305 return FALSE; 04306 } 04307 04308 SetCurrentStates(); 04309 04310 // We now need to work out if the Mouse is currently over part of the document - if it isn't 04311 // then we should ignore the message and let something else handle it... 04312 Spread* pSpread = Document::GetSelectedSpread(); 04313 if (pSpread == NULL) { return FALSE; } 04314 04315 DocCoord MousePos; 04316 if(!DocView::GetCurrentMousePos(&pSpread, &MousePos)) 04317 { 04318 return FALSE; 04319 } 04320 04321 04322 #if (_OLE_VER >= 0x200) 04323 // The user's doing something so don't update any container docs 04324 CCamDoc::ResetContainerUpdateTimer(); 04325 #endif 04326 04327 //If the user is holding down CTRL whilst scrolling the wheel, then we should do the standard zoom-in/out 04328 if (event.ControlDown()) 04329 { 04330 // TRACEUSER( "Matt", _T("MouseWheel + CTRL = Zoom, in ScreenView\n")); 04331 04332 // Try to create an instance of the zoom operation. 04333 OpZoom* pZoomOp = new OpZoom; 04334 if (pZoomOp == NULL) 04335 { 04336 // We ran out of memory, so sorry. 04337 InformError(_R(IDE_NOMORE_MEMORY)); 04338 return FALSE; 04339 } 04340 04341 DocCoord DocMouse = MousePos.ToDoc(pSpread, pDocView); 04342 WorkCoord WorkMouse; 04343 WorkMouse = DocMouse.ToWork(pSpread, pDocView); 04344 04345 // Get the current view's scaling factor as a rounded precentage. 04346 INT32 nOldScalePercent = ((pDocView->GetViewScale() * 100) + FIXED16_DBL(0.5)).MakeInt(); 04347 04348 // Zoom in or out around the mouse position... 04349 if (zDelta > 0) 04350 { 04351 // Search backwards until we find a higher zoom, or the end of the table 04352 for (INT32 i = cZoomTableSize - 1; i >= 0; i--) 04353 { 04354 // Found a higher zoom? If so, set it, remember it's position and return. 04355 if (nOldScalePercent < pZoomOp->GetPresetZoomPercent(i)) 04356 { 04357 // Do the zoom. We will (optionally) end the operation. 04358 pDocView->SetZoomTableIndex(i); 04359 pZoomOp->MouseWheelZoomAtPoint(WorkMouse, pZoomOp->GetPresetZoomScale(i), FALSE); 04360 break; 04361 } 04362 } 04363 } 04364 else 04365 { 04366 // Search forwards through the zoom table until we find a lower zoom factor 04367 for (INT32 i = 0; i < cZoomTableSize; i++) 04368 { 04369 // Found a lower zoom? If so, set it, remember it's position in the zoom table 04370 if (nOldScalePercent > pZoomOp->GetPresetZoomPercent(i)) 04371 { 04372 // Do the zoom. We will (optionally) end the operation. 04373 pDocView->SetZoomTableIndex(i); 04374 pZoomOp->MouseWheelZoomAtPoint(WorkMouse, pZoomOp->GetPresetZoomScale(i), FALSE); 04375 break; 04376 } 04377 } 04378 } 04379 04380 // Tidy away... 04381 delete pZoomOp; 04382 04383 return TRUE; 04384 } 04385 else 04386 { 04387 // The CTRL key was not pressed, so we should simply (is anything simple around here) 04388 // scroll the viewport up/down. (OR left/right if SHIFT is held down - Matt 16/11/2000) 04389 04390 if (event.ShiftDown()) 04391 { 04392 // Get the current Horizontal Scroll Position, increment it by a zoom-dependent amount 04393 // and set the Horizontal Scroll Position to be this value, flagging it to redraw... 04394 ScrollBy(-(zDelta/zStep) * 20, 0); 04395 } 04396 else 04397 { 04398 // Get the current Vertical Scroll Position, increment it by a zoom-dependent amount 04399 // and set the Vertical Scroll Position to be this value, flagging it to redraw... 04400 ScrollBy(0, -(zDelta/zStep) * 20); 04401 } 04402 04403 // NOTE : If we wanted to be really flash, we could make the scroll distance affected by the 04404 // user's settings in the Control Panel - ie, default is to scroll 3 lines on 120 zDelta, but 04405 // can be adjusted so we could look at that value... 04406 } 04407 // tell everyone we've changed the screen 04408 BROADCAST_TO_ALL(ScreenChangeMsg()); 04409 } 04410 04411 // If we get to here, then we must have handled the MouseWheel, so return true... 04412 return TRUE; 04413 } 04414 04415 04416 04417 /********************************************************************************************* 04418 > void CCamView::HandleButtonUp(UINT32 nFlags, wxPoint point) 04419 04420 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 04421 Created: 9th Sept 1993 04422 Inputs: Button - which mouse button has been released. 04423 nFlags - The mouse button flags. 04424 point - the coordinate of the mouse cursor. 04425 Outputs: - 04426 Returns: - 04427 Purpose: Finishes the current drag, if there is one, by elucidating the state of 04428 the buttons etc and calling DragDFinished() in the kernel (DocView). Called 04429 whenever a mouse button is released. 04430 Errors: - 04431 Scope: Private 04432 SeeAlso: CCamView::GetClickMods(); CCamView::OnLButtonDown(); CCamView::OnRButtonDown() 04433 DocView::OnClick() 04434 04435 **********************************************************************************************/ 04436 04437 void CCamView::HandleButtonUp(UINT32 Button, wxMouseEvent &event) 04438 { 04439 //Graham 18/6/96: Changed the logical conditions of this function 04440 //to support clicks with one mouse button while another button is 04441 //dragging 04442 04443 if (DocView::GetSelected() != pDocView) 04444 { 04445 ENSURE(pCurrentDragOp == NULL, "Drag operation in a view that isn't 'selected' !!"); 04446 // TRACEUSER( "JustinF", _T("Ignored button-up cos not in the selected view\n")); 04447 return; 04448 } 04449 04450 // Set Current states... 04451 SetCurrentStates(); 04452 04453 //Graham: Here's the change - in the logical conditions only. The actual 04454 //functions called are the same. 04455 04456 WinCoord point; 04457 event.GetPosition( &point.x, &point.y ); 04458 04459 //Was the button that went up the first one that went down? 04460 if (Button==FirstClickButton) 04461 { 04462 //Yes it was. 04463 //Is there a drag currently running? 04464 if (pCurrentDragOp != NULL) 04465 { 04466 // Yes there is. 04467 // Release the capture and terminate the drag. Note that we try to release 04468 // the mouse capture as soon as possible after a drag has finished, in case the 04469 // DragFinished method below brings up a dialog box or something. 04470 if (GetRenderWindow() && GetRenderWindow()->GetCapture()==GetRenderWindow()) 04471 GetRenderWindow()->ReleaseMouse(); 04472 pDocView->DragFinished(pCurrentDragOp, ((WinCoord*) &point)->ToOil(pDocView, TRUE), 04473 LastClickMods, TRUE); 04474 04475 04476 // Now cater for the special case that the user used the PushCentreTool Click Modifier 04477 // and they didn't move the mouse - this means they either wanted to Centre the 04478 // view about the cursor, ZoomIn() or ZoomOut() depending on the modifiers.... 04479 if ((LastClickPoint == CurrentMousePos) && LastClickMods.PushCentreTool) 04480 { 04481 // Did we want to ZoomIn()? 04482 if( event.ControlDown() ) 04483 { 04484 OpZoom* pZoomOp = new OpZoom; 04485 ERROR3IF(!pZoomOp,"Couldn't create pZoomOp"); 04486 04487 // Find the mid-point of the view, in work coordinates... 04488 WorkRect wrView = pDocView->GetViewRect(); 04489 WorkCoord wcMidView((wrView.lo.x + wrView.hi.x) / 2, (wrView.lo.y + wrView.hi.y) / 2); 04490 04491 pZoomOp->ZoomIn(wcMidView); 04492 } 04493 // Did we want to ZoomOut()? 04494 else if( event.ShiftDown() ) 04495 { 04496 OpZoom* pZoomOp = new OpZoom; 04497 ERROR3IF(!pZoomOp,"Couldn't create pZoomOp"); 04498 04499 // Find the mid-point of the view, in work coordinates... 04500 WorkRect wrView = pDocView->GetViewRect(); 04501 WorkCoord wcMidView((wrView.lo.x + wrView.hi.x) / 2, (wrView.lo.y + wrView.hi.y) / 2); 04502 04503 pZoomOp->ZoomOut(wcMidView); 04504 } 04505 else 04506 { 04507 // Then we must have wanted to centre the screen about the cursor... 04508 04509 DocCoord MousePos; 04510 Spread *pSpread = Document::GetSelectedSpread(); 04511 if(!DocView::GetCurrentMousePos(&pSpread, &MousePos)) 04512 { 04513 return; 04514 } 04515 04516 04517 WorkCoord testwork(MousePos.ToWork(pSpread, pDocView)); 04518 04519 04520 // Find out where the middle of the current view is... 04521 DocRect ViewRect = (pDocView->GetDocViewRect(pSpread)).ToSpread(pSpread, pDocView); 04522 DocCoord ViewMidPoint(0,0); 04523 ViewMidPoint.x = INT32(ViewRect.lo.x + (ViewRect.hi.x - ViewRect.lo.x)/2.0); 04524 ViewMidPoint.y = INT32(ViewRect.lo.y - (ViewRect.lo.y - ViewRect.hi.y)/2.0); 04525 04526 // Work out what the offset between the centre of the screen and the MousePos is... 04527 DocCoord Offset = MousePos - ViewMidPoint; 04528 04529 WorkCoord ScrollOffset; 04530 WorkCoord WorkOffset; 04531 04532 WorkOffset.x = (XLONG) (MakeXLong(Offset.x) * pDocView->GetViewScale()); 04533 WorkOffset.y = (XLONG) (MakeXLong(Offset.y) * pDocView->GetViewScale()); 04534 04535 ScrollOffset = pDocView->GetScrollOffsets(); 04536 ScrollOffset.x = ScrollOffset.x + WorkOffset.x; 04537 ScrollOffset.y = ScrollOffset.y + WorkOffset.y; 04538 04539 if (ScrollOffset.x < (XLONG) 0) ScrollOffset.x = (XLONG) 0; 04540 if (ScrollOffset.y > (XLONG) 0) ScrollOffset.y = (XLONG) 0; 04541 04542 // Scroll the screen to centre about the cursor! 04543 pDocView->SetScrollOffsets(ScrollOffset, TRUE); 04544 } 04545 } 04546 } 04547 else 04548 { 04549 // No there isn't. 04550 // Kill the timer started in HandleDragEvent(), 04551 // as we don't want to wait for a drag anymore. 04552 m_DragIdleTimer.Stop(); 04553 04554 FirstClickButton = 0; 04555 04556 //Then pass the Up-Click message to CCamView::OnClick 04557 pDocView->OnClick(((WinCoord*) &point)->ToOil(pDocView, TRUE), CLICKTYPE_UP, LastClickMods); 04558 } 04559 } 04560 else 04561 { 04562 //No, the button that went up was not the first one to go down. 04563 //In that case, we expect the first button that went down is still down and 04564 //hence there is a drag running. 04565 //Is there a drag running? 04566 if (pCurrentDragOp != NULL) 04567 { 04568 //Yes, as expected. 04569 //Pass the Up-Click message to CCamView::OnClick 04570 pDocView->OnClick(((WinCoord*) &point)->ToOil(pDocView, TRUE), CLICKTYPE_UP, LastClickMods); 04571 } 04572 //If not, something odd has happened - perhaps the user has clicked fast 04573 //with the mouse. This need not worry us but we should not do anything 04574 //with the up-click message. 04575 //The only problem that could occur is if we are in a button-up-drag. This 04576 //is handled below. 04577 04578 } 04579 04580 //Ensure there is not a button-up drag in progress 04581 //That is, there is a drag in progress AND no buttons down 04582 // ERROR3IF((Operation::GetCurrentDragOp()==NULL)&&(nFlags & ~(MK_SHIFT | MK_CONTROL) == 0), 04583 // "CCamView::HandleButtonUp - drag operation in progress but no buttons down"); 04584 } 04585 04586 // The following is Justin's original logical conditions, commented out, in case 04587 // anyone needs them or if the above doesn't work 04588 /* // Are we in a real mess, Mr User? 04589 if (Button != FirstClickButton) 04590 { 04591 // TRACEUSER( "JustinF", _T("Ignored button-up cos different button went down\n")); 04592 return; 04593 } 04594 04595 04596 04597 // Are we currently running a drag operation. 04598 if (pCurrentDragOp != NULL) 04599 { 04600 // Yes, so release the capture and terminate the drag. Note that we try to release 04601 // the mouse capture as soon as possible after a drag has finished, in case the 04602 // DragFinished method below brings up a dialog box or something. 04603 ::ReleaseCapture(); 04604 pDocView->DragFinished(pCurrentDragOp, ((WinCoord*) &point)->ToOil(pDocView, TRUE), 04605 LastClickMods, TRUE); 04606 } 04607 else 04608 { 04609 // No. Is this the button that was pressed first? If so, kill the timer started in 04610 // HandleDragEvent(), as we don't want to wait for a drag anymore. 04611 if (Button == FirstClickButton) 04612 { 04613 ::FixKillTimer(m_hWnd, 1); 04614 FirstClickButton = 0; 04615 } 04616 else 04617 { 04618 // NB. the test above should prevent this ENSURE going off . . . 04619 ENSURE((nFlags & ~(MK_SHIFT | MK_CONTROL)) == 0, 04620 "No buttons down - Welcome to Button-Up-Drag City!"); 04621 } 04622 04623 // Send a button-up event if we weren't running a drag. 04624 pDocView->OnClick(((WinCoord*) &point)->ToOil(pDocView, TRUE), CLICKTYPE_UP, LastClickMods); 04625 04626 }*/ 04627 04628 04629 04630 /********************************************************************************************* 04631 > BOOL CCamView::InvokeDragOp(String_256 OpToken,UINT32 Flags,wxPoint point,OpParam* pParam) 04632 > BOOL CCamView::InvokeDragOp(String_256 OpToken,ClickModifiers clickmods,wxPoint point,OpParam* pParam) 04633 04634 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 04635 Created: 21/9/95 04636 Inputs: OpToken = Op token of op to invoke 04637 pParam = ptr to a param block that's passed to the op 04638 NOTE! Object at *pParam must have a long life time. I.e. do NOT 04639 call this func with ptr to a local OpParam var 04640 Flags = flags that specify which modifiers were down during the click 04641 clickmods = Kernel abstraction of modifiers 04642 point = screen coord of the start of the drag 04643 Outputs: - 04644 Returns: Returns TRUE if successful. Returns FALSE if not 04645 Purpose: This func provides a mechanism that allows a drag op to be invoked as if it has been started 04646 as a result of clicking in the view. This allows drag ops to be invoked that aren't 04647 associated to a given tool. 04648 04649 This allows a drag op to be started directly, instead of being a result of a tool handling 04650 the click. This allows you to write drag ops in the usual way. 04651 04652 If pParam is NULL, the op's Do() function will be called. If pParam != NULL, the op's 04653 DoWithParam(pParam) func will be called. Either way, Operation::StartDrag() should be 04654 called as a result. 04655 04656 It was introduced to allow the rulers to create guidelines undoably, no matter what 04657 tool you are in. See winoil\oilruler.cpp & kernel\guides.cpp & OpGuideLine 04658 04659 Errors: - 04660 Scope: - 04661 SeeAlso: - 04662 04663 **********************************************************************************************/ 04664 /* Implementation notes: 04665 04666 It does this: 04667 Posts itself a WM_LBUTTONDOWN message with the flags and point provided 04668 NOTE: Not any more! Now calls HandleDragEvent directly... 04669 04670 and in HandleDragEvent() 04671 Creates an instance of the op specified by OpToken 04672 Calls the DragStart() virt func, that should call Operation::StartDrag() at some point 04673 */ 04674 04675 BOOL CCamView::InvokeDragOp(String_256* pOpToken,OpParam* pParam,UINT32 Flags,wxPoint point) 04676 { 04677 DragOpToken = *pOpToken; 04678 pDragOpParam = pParam; 04679 DragOpInvoke = TRUE; 04680 04681 // NOTE: May need to post a pseudo mouse event here if some of the subtleties of click 04682 // handling are required, but this works fine for simple drags 04683 HandleDragEvent(MK_LBUTTON, Flags, point, CLICKTYPE_SINGLE); 04684 04685 return TRUE; 04686 } 04687 04688 BOOL CCamView::InvokeDragOp(String_256* pOpToken, OpParam* pParam, ClickModifiers clickmods, wxPoint point) 04689 { 04690 DragOpToken = *pOpToken; 04691 pDragOpParam = pParam; 04692 DragOpInvoke = TRUE; 04693 04694 // NOTE: May need to post a pseudo mouse event here if some of the subtleties of click 04695 // handling are required, but this works fine for simple drags 04696 HandleDragEvent(MK_LBUTTON, clickmods, point, CLICKTYPE_SINGLE); 04697 04698 return TRUE; 04699 } 04700 04701 04702 04703 04704 04705 04706 04707 04708 /******************************************************************************************** 04709 04710 > BOOL CCamView::ChangeDragType(DragType Type) 04711 04712 Author: Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> 04713 Created: 3/4/95 04714 Inputs: Type - the type of drag to change to 04715 Returns: TRUE 04716 Purpose: Allows someone to change the type of a drag (eg have Auto Scrolling on 04717 in some situations, but not in others). This function is mostly called from 04718 the Kernel (DocView) version of the same function 04719 SeeAlso: DocView::ChangeDragType 04720 04721 ********************************************************************************************/ 04722 04723 BOOL CCamView::ChangeDragType(DragType Type) 04724 { 04725 // Change the current drag type 04726 CurrentDragType = Type; 04727 m_OLELastOutTime.Sample(); 04728 OLERecaptureMouse = FALSE; 04729 04730 return TRUE; 04731 } 04732 04733 04734 /********************************************************************************************* 04735 > void CCamView::HandleDragScrolling(wxPoint point) 04736 04737 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 04738 Created: 20th Sept 1993 04739 Inputs: The current position of the mouse cursor. 04740 Outputs: - 04741 Returns: - 04742 Purpose: Checks if the view window needs to be scrolled because the cursor has been 04743 dragged outside the window. The window will be scrolled if the current 04744 mode is AUTO_SCROLL (and the Scroll Lock key isn't latched!!). The scrolling 04745 itself is done by calling the routine in DocView, not ScreenView, so that the 04746 kernel has fair warning to remove any blobbies before the blit is done. 04747 04748 Called when ScreenView receives mouse-move messages and timer ("mouse-idle") 04749 messages. Also handles DEFERRED_SCROLLING. 04750 Errors: - 04751 Scope: Private 04752 SeeAlso: CCamView::OnMouseMove; CCamView::OnTimer 04753 04754 **********************************************************************************************/ 04755 04756 void CCamView::HandleDragScrolling(wxPoint point) 04757 { 04758 // First we check for the type that does nothing and get out quick 04759 if (CurrentDragType == DRAGTYPE_NOSCROLL) 04760 return; 04761 04762 // Get the size of the view. We may have to deflate the rectangle a little here, if the 04763 // bottom-right edges of the view coincide with the bottom-right edges of the screen, 04764 // otherwise it is not possible to auto-scroll to the right or down as the mouse never 04765 // leaves the view window. 04766 04767 WinRect wrSize = CurrentSize; 04768 // TRACEUSER("Gerry", _T("wrSize = (%d, %d) [%d, %d]\n"), wrSize.x, wrSize.y, wrSize.width, wrSize.height); 04769 // TRACEUSER("Gerry", _T("Point = (%d, %d)\n"), point.x, point.y); 04770 point = GetRenderWindow()->ClientToScreen( point ); 04771 point = GetFrame()->ScreenToClient( point ); 04772 04773 // TRACEUSER("Gerry", _T("AdjPoint = (%d, %d)\n"), point.x, point.y); 04774 04775 // This is used to allow guidelines to be deleted by dropping on to the rulers - normally 04776 // we would start to auto scroll at this point which is a little off putting.. 04777 if (AutoScrollExcludeRulers && CurrentDragType != DRAGTYPE_OLESCROLL) 04778 { 04779 UINT32 RulerWidth = OILRuler::GetWidth(); 04780 // wrSize.left -= RulerWidth; 04781 // wrSize.top -= RulerWidth; 04782 wrSize.SetLeft(wrSize.GetLeft()-RulerWidth); 04783 wrSize.SetTop(wrSize.GetTop()-RulerWidth); 04784 } 04785 04786 // Now check for deferred scrolling 04787 if (CurrentDragType == DRAGTYPE_DEFERSCROLL) 04788 { 04789 // If the mouse is within the window, and we are performing deferred-scrolling 04790 // then we can change over to auto-scrolling. 04791 if (!wrSize.IsEmpty() && wrSize.Inside(point)) 04792 { 04793 CurrentDragType = DRAGTYPE_AUTOSCROLL; 04794 AutoScrollExcludeRulers = TRUE; 04795 } 04796 return; 04797 } 04798 04799 // Initialise Deltas... 04800 INT32 dx = 0; 04801 INT32 dy = 0; 04802 04803 WinRect Outer = wrSize; 04804 04805 // Set auto-scroll region to be one scrollbar width within the current view 04806 // (as per The Windows Interface Guidelines Chapter 5). 04807 wrSize.Inflate(-ScrollBarSize,-ScrollBarSize); 04808 04809 // Has the mouse moved outside there bounds? 04810 if (!wrSize.IsEmpty() && !wrSize.Inside(point)) 04811 { 04812 BOOL bCalcDeltas = TRUE; 04813 #if !defined(EXCLUDE_FROM_XARALX) 04814 if (CurrentDragType == DRAGTYPE_OLESCROLL) 04815 { 04816 if (Outer.Inside(point)) // and still inside visible window 04817 { 04818 // If we've not been in the OLE scroll region for long enough 04819 if (!m_OLELastOutTime.Elapsed(100)) 04820 { 04821 bCalcDeltas = FALSE; 04822 } 04823 } 04824 else 04825 { 04826 // We've dragged beyond the OLE scroll area, so we can now convert the drag 04827 // into an OLE export drag if we so desire. 04828 HandleOleDragOutOfView(point); 04829 bCalcDeltas = FALSE; 04830 } 04831 } 04832 #endif 04833 if (bCalcDeltas) 04834 { 04835 // The mouse is outside the view, and we have to scroll the view 04836 // proportionate to how far outside it is. 04837 CalcScrollDeltas(point,wrSize,&dx,&dy); 04838 TRACEUSER("Gerry", _T("ScrollDeltas = (%d, %d)\n"), dx, dy); 04839 } 04840 } 04841 #if !defined(EXCLUDE_FROM_XARALX) 04842 else if (CurrentDragType == DRAGTYPE_OLESCROLL) 04843 { 04844 // We're not in the OLE scroll region so reset the timer 04845 m_OLELastOutTime.Sample(); 04846 } 04847 #endif 04848 04849 //------------------------------------ 04850 // Now do the scroll if necessary... 04851 // If dx<>0 or dy<>0 and scroll lock is disabled 04852 04853 // Test if the SCROLL LOCK key has been set. 04854 if( !wxGetKeyState( CAMKEY(SCROLL) ) && !(dx==0 && dy==0)) 04855 { 04856 // Set Current states... 04857 SetCurrentStates(); 04858 04859 // Do the scroll 04860 ScrollBy(dx, dy); 04861 } 04862 } 04863 04864 04865 /********************************************************************************************* 04866 > static void CCamView::GetClickMods(wxMouseEvent &event, ClickModifiers* p) 04867 04868 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 04869 Created: ages ago 04870 Inputs: The mouse event passed by wx to a mouse message-handler function. 04871 Outputs: Changes the ClickModifier to reflect the button flags. 04872 Returns: - 04873 Purpose: Helps convert an OIL-layer mouse event into a form acceptable to the kernel. 04874 Sets the fields of the ClickModifier according to which button is down/up, 04875 whether the SHIFT, CONTROL, or ALT key is held down etc. Note that as the 04876 fields of a ClickModifier are only one bit wide, we must be carefule when 04877 assigning the (integer) results of logical tests to them. 04878 Errors: - 04879 Scope: Public 04880 SeeAlso: CCamView::HandleDragEvent() 04881 **********************************************************************************************/ 04882 04883 void CCamView::GetClickMods(wxMouseEvent &event, ClickModifiers* p) 04884 { 04885 *p = ClickModifiers::GetClickModifiers(event); 04886 } 04887 04888 04889 /********************************************************************************************* 04890 > void CCamView::CalcScrollDeltas(wxPoint point, WinRect wrSize, INT32* dx, INT32* dy) 04891 04892 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> (from Justin) 04893 Created: 22/9/96 04894 Inputs: point The current position of the mouse cursor. 04895 wrSize The rectangle controlling scrolling. 04896 Outputs: dx The amount to scroll in the X axis. 04897 dy The amount to scroll in the Y axis. 04898 Returns: - 04899 Purpose: Calculates the scroll deltas due to the current mouse position being 04900 outside the allowed rectangle. 04901 Helper function. 04902 Errors: - 04903 Scope: Protected 04904 SeeAlso: CCamView::HandleDragScrolling 04905 04906 **********************************************************************************************/ 04907 04908 void CCamView::CalcScrollDeltas(wxPoint point, WinRect wrSize, INT32* dx, INT32* dy) 04909 { 04910 if( point.x < wrSize.GetLeft() ) 04911 *dx = max(point.x - wrSize.GetLeft(), -ScrollBarSize); 04912 else if( point.x >= wrSize.GetRight() ) 04913 *dx = min(point.x - wrSize.GetRight(), ScrollBarSize); 04914 else 04915 *dx = 0; 04916 04917 if( point.y < wrSize.GetTop() ) 04918 *dy = max(point.y - wrSize.GetTop(), -ScrollBarSize); 04919 else if( point.y >= wrSize.GetBottom() ) 04920 *dy = min(point.y - wrSize.GetBottom(), ScrollBarSize); 04921 else 04922 *dy = 0; 04923 } 04924 04925 04926 /********************************************************************************************* 04927 > void CCamView::ScrollBy(INT32 dx, INT32 dy) 04928 04929 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> (from Justin) 04930 Created: 22/9/96 04931 Inputs: dx The amount to scroll in the X axis. 04932 dy The amount to scroll in the Y axis. 04933 Returns: - 04934 Purpose: Scrolls the view by asking the DocView to do it so it can remove 04935 and replace blobs. 04936 Errors: - 04937 Scope: Protected 04938 04939 **********************************************************************************************/ 04940 04941 void CCamView::ScrollBy(INT32 dx, INT32 dy) 04942 { 04943 // If we're not scrolling then don't bother 04944 if (dx == 0 && dy == 0) 04945 return; 04946 04947 // Convert these pixel values into a WorkCoord offset, add to the 04948 // scroll position and update the scroll bars etc. Note that the 04949 // y offset is subtracted as the y-axis is reversed compared to 04950 // Windows . . . 04951 WorkCoord offset; 04952 GetScrollOffset(&offset); 04953 // TRACEUSER("Gerry", _T("OldOffset = (%d, %d)\n"), (INT32)offset.x, (INT32)offset.y); 04954 04955 FIXED16 PixelWidth, PixelHeight; 04956 pDocView->GetPixelSize(&PixelWidth, &PixelHeight); 04957 offset.x += dx * PixelWidth; 04958 offset.y -= dy * PixelHeight; 04959 04960 WorkRect wrScrollRect = GetMaxScrollRect(); 04961 if (offset.x < wrScrollRect.lo.x) offset.x = wrScrollRect.lo.x; 04962 if (offset.y < wrScrollRect.lo.y) offset.y = wrScrollRect.lo.y; 04963 if (offset.x > wrScrollRect.hi.x) offset.x = wrScrollRect.hi.x; 04964 if (offset.y > wrScrollRect.hi.y) offset.y = wrScrollRect.hi.y; 04965 // TRACEUSER("Gerry", _T("NewOffset = (%d, %d)\n"), (INT32)offset.x, (INT32)offset.y); 04966 04967 // By calling DocView to do the scroll we give it a chance to remove 04968 // any blobbies it might have put on the screen. Note that the scrollers 04969 // will prevent any overscroll. 04970 pDocView->SetScrollOffsets(offset, TRUE); 04971 } 04972 04973 04974 /******************************************************************************************** 04975 > WorkRect CCamView::GetMaxScrollRect() const 04976 04977 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 04978 Created: 31/May/2006 04979 Inputs: - 04980 Outputs: - 04981 Returns: WorkRect describing legal area for scroll offsets 04982 Purpose: Find the legal area in which scroll offsets can exist 04983 Errors: - 04984 SeeAlso: - 04985 ********************************************************************************************/ 04986 04987 WorkRect CCamView::GetMaxScrollRect() const 04988 { 04989 WorkRect wrScrollRect = Status->WorkAreaExtent; 04990 04991 FIXED16 PixelWidth, PixelHeight; 04992 pDocView->GetPixelSize(&PixelWidth, &PixelHeight); 04993 04994 WorkCoord WindowSize; 04995 WindowSize.x = CurrentSize.GetWidth() * PixelWidth; 04996 WindowSize.y = CurrentSize.GetHeight() * PixelHeight; 04997 04998 if (WindowSize.x > wrScrollRect.hi.x) // If window wider than document 04999 wrScrollRect.hi.x = wrScrollRect.lo.x; // no horz scrolling is possible 05000 else 05001 wrScrollRect.hi.x -= WindowSize.x; // Restrict scrollable area to ensure view never sees outside workarea 05002 05003 if (WindowSize.y < wrScrollRect.lo.y) // If window wider than document 05004 wrScrollRect.lo.y = wrScrollRect.hi.y; // no vert scrolling is possible 05005 else 05006 wrScrollRect.lo.y += WindowSize.y; // Restrict scrollable area to ensure view never sees outside workarea 05007 05008 return wrScrollRect; 05009 } 05010 05011 05012 /******************************************************************************************** 05013 > BOOL CCamView::IsTopmost() const 05014 05015 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 05016 Created: 17/11/93 05017 Inputs: - 05018 Outputs: - 05019 Returns: TRUE if this view is the active view. 05020 Purpose: Tests if this ScreenView is the active view, ie. is on top of all other views. 05021 Errors: - 05022 SeeAlso: - 05023 ********************************************************************************************/ 05024 05025 BOOL CCamView::IsTopmost() const 05026 { 05027 return( wxGetApp().CCamApp::GetDocumentManager()->GetCurrentView() == this ); 05028 } 05029 05030 05031 /******************************************************************************************** 05032 > static DocView* CCamView::GetDocViewFromWindow(wxWindow* pWindow) 05033 05034 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 05035 Created: 28/7/94 05036 Inputs: The handle of the render window to find. 05037 Outputs: - 05038 Returns: A pointer to the DocView associated with a render window, or NULL if 05039 there isn't one. 05040 Purpose: Given a window handle of a ScreenView render window, this function will 05041 return a pointer to the kernel DocView object that renders into that 05042 window, or NULL if there isn't one. 05043 Errors: - 05044 SeeAlso: - 05045 ********************************************************************************************/ 05046 05047 DocView *CCamView::GetDocViewFromWindow(wxWindow *pWindow) 05048 { 05049 // For all kernel documents in existence . . . 05050 List* pDocList = &(GetApplication()->Documents); 05051 for (Document* pKernelDoc = (Document*) pDocList->GetHead(); 05052 pKernelDoc != NULL; 05053 pKernelDoc = (Document*) pDocList->GetNext(pKernelDoc)) 05054 { 05055 if (pKernelDoc->IsARalphDoc()) 05056 { 05057 // a bit unpleasent - only works because Ralph Docs have only one view.. 05058 // get the first (and only) docview 05059 DocView * pDocView = pKernelDoc->GetFirstDocView(); 05060 // check handles 05061 if (pDocView) 05062 if( pDocView->GetRenderWindow() == pWindow ) 05063 return pDocView; 05064 } 05065 else 05066 { 05067 // Convert from a kernel document to an OIL document. 05068 CCamDoc* pCamDoc = pKernelDoc->GetOilDoc(); 05069 05070 wxNode *node = pCamDoc->GetViews().GetFirst(); 05071 while (node) 05072 { 05073 // Compare the handle of the view's render window to the given handle, 05074 // returning the associated DocView if they match. 05075 CCamView* pCamView = (CCamView*) node->GetData(); 05076 05077 // Not interested unless it is a ScreenView (it could be a print preview view) 05078 // if (pCamView->IsKindOf(RUNTIME_CLASS(CCamView))) 05079 // { 05080 if (pCamView->GetRenderWindow() == pWindow) 05081 { 05082 return pCamView->pDocView; 05083 } 05084 // } 05085 node = node->GetNext(); 05086 } 05087 } 05088 } 05089 05090 // Couldn't find the handle, so return nothing. 05091 return NULL; 05092 } 05093 05094 05095 /********************************************************************************************* 05096 > BOOL CCamView::CreateDragTarget(DragInformation * DragInfo) 05097 05098 Author: Chris_Parks (Xara Group Ltd) <camelotdev@xara.com> 05099 Created: 21/1/95 05100 Inputs: DragInfo : details about the current drag 05101 Outputs: - 05102 Purpose: will create drag targets for appropriate drags 05103 Errors: - 05104 05105 **********************************************************************************************/ 05106 05107 BOOL CCamView::CreateDragTarget(DragInformation * DragInfo) 05108 { 05109 #if !defined(EXCLUDE_FROM_RALPH) 05110 // TEMPORARY - only create drag targets for the selected (frontmost/input-focus) 05111 // DocView. This stops us allowing colour drags to go into the wrong document 05112 // if the user ctrl-tabs to a different window during the drag. 05113 // Ideally, drags will be allowed, but the colour will be copied to the destination 05114 // document before being applied, but currently we don't have time to implement all that 05115 if (pDocView != DocView::GetSelected()) 05116 return FALSE; 05117 05118 if (DragInfo->CanDropOnPage()) 05119 { 05120 // If the drag can be dropped onto an object or the page, then we will accept it 05121 ViewDragTarget * NewTarget; 05122 NewTarget = new ViewDragTarget(RenderWindow,NULL,DragInfo); 05123 return TRUE; 05124 } 05125 #endif 05126 return FALSE; 05127 } 05128 05129 05130 /******************************************************************************************** 05131 > static DocView* CCamView::GetDocViewFromHwnd(CWindowID WindowID) 05132 05133 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 05134 Created: 28/7/94 05135 Inputs: The handle of the render window to find. 05136 Outputs: - 05137 Returns: A pointer to the DocView associated with a render window, or NULL if 05138 there isn't one. 05139 Purpose: Given a window handle of a ScreenView render window, this function will 05140 return a pointer to the kernel DocView object that renders into that 05141 window, or NULL if there isn't one. 05142 Errors: - 05143 SeeAlso: - 05144 ********************************************************************************************/ 05145 05146 DocView *CCamView::GetDocViewFromWindowID( CWindowID WindowID ) 05147 { 05148 // For all kernel documents in existence . . . 05149 List* pDocList = &(GetApplication()->Documents); 05150 for (Document* pKernelDoc = (Document*) pDocList->GetHead(); 05151 pKernelDoc != NULL; 05152 pKernelDoc = (Document*) pDocList->GetNext(pKernelDoc)) 05153 { 05154 05155 DocView * pDocView = pKernelDoc->GetFirstDocView(); 05156 05157 while (pDocView) 05158 { 05159 if ( pDocView->GetRenderWindow() == WindowID ) 05160 return pDocView; 05161 pDocView = pKernelDoc->GetNextDocView(pDocView); 05162 } 05163 } 05164 05165 // Couldn't find the handle, so return nothing. 05166 return NULL; 05167 } 05168 05169 05170 bool CCamView::OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& filenames) 05171 { 05172 // Set the correct docivew (and hence document) 05173 pDocView->SetCurrent(); 05174 05175 // Create the drop info object 05176 FileDropInfo DropInfo(WinCoord(x, y)); 05177 List* pList = DropInfo.GetFileList(); 05178 05179 size_t Index; 05180 for (Index = 0; Index < filenames.GetCount(); Index++) 05181 { 05182 wxString TempStr(filenames[Index]); 05183 05184 // A bit of a nasty hack here to work around a bug in wxWidgets 05185 // Filenames with multibyte characters are not correctly decoded 05186 // into the wxString so it still contains multi-byte sequences 05187 // We will check if all the chars are single byte and if so, 05188 // force it into a char buffer and convert using wxConvFileName 05189 // This should mean that this code will not interfere if someone 05190 // fixes wxWidgets 05191 UINT32 i = 0; 05192 while (TempStr[i] != 0 && (TempStr[i] & 0xFF) == TempStr[i]) 05193 i++; 05194 05195 if (TempStr[i] == 0) 05196 { 05197 // All the chars are bytes so try sticking them into a char array 05198 // and converting them with wxConvFileName 05199 char* pBuf = (char*)CCMalloc(i + 1); 05200 if (pBuf) 05201 { 05202 i = 0; 05203 while (TempStr[i] != 0) 05204 { 05205 pBuf[i] = (char)(TempStr[i] & 0xFF); 05206 i++; 05207 } 05208 pBuf[i] = 0; 05209 05210 TempStr = wxConvFileName->cMB2WX(pBuf); 05211 CCFree(pBuf); 05212 } 05213 } 05214 05215 String_256 Str(TempStr); 05216 05217 StringListItem* pItem = new StringListItem(Str); 05218 if (pItem) 05219 pList->AddTail(pItem); 05220 } 05221 05222 // Invoke the dropped files operation 05223 OpDescriptor *pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_DROPPEDFILE); 05224 if (pOpDesc) 05225 pOpDesc->Invoke((OpParam *) &DropInfo); 05226 05227 return(true); 05228 } 05229 05230 05231 /******************************************************************************************** 05232 05233 > void ViewDragTarget::ViewDragTarget() 05234 05235 Author: Chris_Snook (Xara Group Ltd) <camelotdev@xara.com> 05236 Created: 12/1/95 05237 Inputs: - 05238 Outputs: - 05239 Returns: - 05240 Purpose: Constructor 05241 Errors: - 05242 SeeAlso: - 05243 05244 ********************************************************************************************/ 05245 ViewDragTarget::ViewDragTarget(wxWindow* TheWindow, wxRect *ClientArea, DragInformation* pDragInfo) 05246 : OilDragTarget(TheWindow,ClientArea) 05247 { 05248 pThisDoc = CCamView::GetDocViewFromWindow(TheWindow); 05249 OverOutline = FALSE; 05250 OverNode = NULL; 05251 05252 pCurrentDragInfo = pDragInfo; 05253 05254 DocView::GetCurrentMousePos(&pSpread, &DropPos); 05255 05256 // Find out the Magnetic Line Radius preference from its owner 05257 LineRad = NodeRenderableBounded::MagneticLineRadius; 05258 05259 // Scale it according to the ScaleFactor. 05260 if (pThisDoc!=NULL) 05261 { 05262 // Get the Scale factor and modify the magnetic radius 05263 double Scale = pThisDoc->GetViewScale().MakeDouble(); 05264 LineRad = (INT32) ((double)LineRad / Scale); 05265 } 05266 05267 } 05268 05269 05270 05271 /******************************************************************************************** 05272 05273 > void ViewDragTarget::GetCursorID() 05274 05275 Author: Chris_Snook (Xara Group Ltd) <camelotdev@xara.com> 05276 Created: 10/1/95 05277 Purpose: Base Method to set cursor over this target 05278 05279 05280 ********************************************************************************************/ 05281 05282 UINT32 ViewDragTarget::GetCursorID() 05283 { 05284 ERROR2IF(pCurrentDragInfo==NULL,FALSE,"No DragInfo available when getting Cursor"); 05285 05286 return pCurrentDragInfo->GetCursorID(this); 05287 } 05288 05289 05290 05291 /******************************************************************************************** 05292 05293 > virtual BOOL ViewDragTarget::GetStatusLineText(String_256 * TheText) 05294 05295 Author: Chris_Snook (Xara Group Ltd) <camelotdev@xara.com> 05296 Created: 15/1/95 05297 Returns: Whether String is valid 05298 Purpose: provide status line text for this target 05299 05300 ********************************************************************************************/ 05301 05302 05303 BOOL ViewDragTarget::GetStatusLineText(String_256 * TheText) 05304 { 05305 ERROR2IF(TheText==NULL,FALSE,"NULL string in GetStatusLineText()"); 05306 ERROR2IF(pCurrentDragInfo==NULL,FALSE,"No DragInfo available when getting Status Text"); 05307 05308 return pCurrentDragInfo->GetStatusLineText(TheText, this); 05309 } 05310 05311 /******************************************************************************************** 05312 05313 > BOOL ViewDragTarget::GetDropInfo(PageDropInfo* pDropInfo) 05314 05315 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 05316 Created: 25/3/95 05317 Inputs: - 05318 Outputs: - 05319 Returns: - 05320 Purpose: Get info about the current drag state of this target 05321 Errors: - 05322 SeeAlso: - 05323 05324 ********************************************************************************************/ 05325 05326 BOOL ViewDragTarget::GetDropInfo(PageDropInfo* pDropInfo) 05327 { 05328 ERROR2IF(pDropInfo==NULL,FALSE,"NULL DropInfo pass to GetDropInfo()"); 05329 05330 pDropInfo->pDocView = pThisDoc; 05331 pDropInfo->pDoc = pThisDoc->GetDoc(); 05332 pDropInfo->pSpread = pSpread; 05333 pDropInfo->DropPos = DropPos; 05334 05335 pDropInfo->TargetHit = OverTarget; 05336 pDropInfo->pObjectHit = OverNode; 05337 05338 return TRUE; 05339 } 05340 05341 /******************************************************************************************** 05342 05343 > void ViewDragTarget::ProcessEvent(DragEventType Event, 05344 DragInformation *pDragInfo, 05345 wxPoint *pMousePos, KeyPress* pKeyPress) 05346 05347 Author: Chris_Snook (Xara Group Ltd) <camelotdev@xara.com> 05348 Created: 12/1/95 05349 Inputs: - 05350 Outputs: - 05351 Returns: - 05352 Purpose: Event Handler for View Drag target 05353 Errors: - 05354 SeeAlso: - 05355 05356 ********************************************************************************************/ 05357 05358 BOOL ViewDragTarget::ProcessEvent(DragEventType Event, 05359 DragInformation *pDragInfo, 05360 wxPoint *pMousePos, KeyPress* pKeyPress) 05361 { 05362 switch (Event) 05363 { 05364 case DRAGEVENT_INITIALISE: 05365 break; 05366 case DRAGEVENT_DEINITIALISE: 05367 break; 05368 case DRAGEVENT_ABORT: 05369 break; 05370 case DRAGEVENT_KEYPRESS: 05371 break; 05372 case DRAGEVENT_COMPLETED: 05373 { 05374 // Do another HitTest check 05375 OverNode = NULL; 05376 DocView::GetCurrentMousePos(&pSpread, &DropPos); 05377 OverTarget = pThisDoc->IsPointerOverNode(&OverNode,LineRad,FALSE,TRUE); 05378 05379 if (!OverNode) OverTarget = NO_TARGET; 05380 05381 // call doc dragfinished to do whatever is needed 05382 return pThisDoc->DM_DragFinished(pDragInfo,this); 05383 break; 05384 } 05385 case DRAGEVENT_MOUSESTOPPED: 05386 case DRAGEVENT_MOUSEMOVED: 05387 case DRAGEVENT_MOUSEIDLE: 05388 { 05389 OverNode = NULL; 05390 DocView::GetCurrentMousePos(&pSpread, &DropPos); 05391 OverTarget = pThisDoc->IsPointerOverNode(&OverNode,LineRad, TRUE, TRUE); 05392 05393 if (!OverNode) OverTarget = NO_TARGET; 05394 05395 return TRUE; 05396 break; 05397 } 05398 default: 05399 break; 05400 } 05401 return FALSE; 05402 } 05403 05404 05405 CViewFileDropTarget::CViewFileDropTarget(CCamView* pView) 05406 { 05407 m_pView = pView; 05408 } 05409 05410 CViewFileDropTarget::~CViewFileDropTarget() 05411 { 05412 } 05413 05414 bool CViewFileDropTarget::OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& filenames) 05415 { 05416 return(m_pView->OnDropFiles(x, y, filenames)); 05417 } 05418