00001 // $Id: grid.cpp 1361 2006-06-25 16:43:38Z 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 // NodeGrid implementation, and associated classes 00099 00100 /* 00101 */ 00102 00103 #include "camtypes.h" 00104 00105 #include <math.h> 00106 00107 //#include "ensure.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00108 //#include "rndrgn.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00109 #include "osrndrgn.h" 00110 #include "paper.h" 00111 //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00112 //#include "markn.h" 00113 //#include "convert.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00114 //#include "spread.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00115 #include "grid.h" 00116 //#include "units.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00117 //#include "document.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00118 #include "chapter.h" 00119 //#include "tool.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00120 00121 //#include "cxfrec.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00122 #include "cxftags.h" 00123 //#include "cxfdefs.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00124 //#include "camfiltr.h" // BaseCamelot filter - in camtypes.h [AUTOMATICALLY REMOVED] 00125 #include "unitcomp.h" // UnitListComponent 00126 00127 const UINT32 MIN_PIX_RENDER_COUNT = 10; // Min distance between rendered grid points, in pixels 00128 const UINT32 PIX_CROSSHAIR_SIZE = 2; // Size of grid crosshair points, in pixels 00129 const INT32 GRID_REND_FACTOR = 128; // Fixed FP for rendering grid 00130 00131 static double mod(double n, double d) { double temp; return (modf(n/d,&temp)*d);} 00132 static double sgn(double n) { if (n<0) return (-1); else return (1); } 00133 00134 static UnitType GetDominantUnit(UnitType ThisUnit); 00135 static double GetUnitMultiple(UnitType Units); 00136 00137 #define Swap(a,b) { (a)^=(b), (b)^=(a), (a)^=(b); } 00138 00139 UINT32 NodeGrid::NumSelected = 0; 00140 UINT32 NodeGrid::NumNonDefaultSelected = 0; 00141 INT32 NodeGrid::LastXDir = 0; 00142 INT32 NodeGrid::LastYDir = 0; 00143 00144 UnitType NodeGrid::DefaultUnits = INCHES; 00145 double NodeGrid::DefaultDivisions = 1.0; 00146 UINT32 NodeGrid::DefaultSubdivisions = 2; 00147 GridType NodeGrid::DefaultGridType = RECTANGULAR; 00148 GridType NodeGrid::TypeForDefaultGrid = RECTANGULAR; 00149 BOOL NodeGrid::DefaultGridDisabled = FALSE; 00150 00151 //-------------------------------------------------------------------------------------------- 00152 // NodeGrid methods 00153 00154 CC_IMPLEMENT_DYNAMIC(NodeGrid, NodeRenderablePaper) 00155 00156 // Declare smart memory handling in Debug builds 00157 #define new CAM_DEBUG_NEW 00158 00159 /********************************************************************************************* 00160 00161 > NodeGrid::NodeGrid() 00162 00163 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00164 Created: 8/2/94 00165 Inputs: - 00166 Outputs: 00167 Returns: - 00168 00169 Purpose: This constructor creates a NodeGrid linked to no other nodes, with all status 00170 flags false, and NULL bounding and pasteboard rectangles. 00171 00172 Errors: 00173 00174 **********************************************************************************************/ 00175 00176 00177 NodeGrid::NodeGrid(): NodeRenderablePaper() 00178 { 00179 SetOrigin(0,0); 00180 GridColour = DocColour(COLOUR_GRID); 00181 00182 GridFlags.Selected = FALSE; 00183 GridFlags.RelativeOrigin = FALSE; 00184 GridFlags.DefaultGrid = FALSE; 00185 GridFlags.Disabled = FALSE; 00186 00187 GridBoundingRect = DocRect(0,0,0,0); 00188 } 00189 00190 00191 00192 /*********************************************************************************************** 00193 00194 > Node* NodeGrid::SimpleCopy() // Private method 00195 00196 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00197 Created: 8/2/94 00198 00199 Inputs: - 00200 Outputs: 00201 Returns: A copy of the node, or NULL if memory runs out 00202 00203 Purpose: This method returns a shallow copy of the node with all Node pointers NULL. 00204 The function is virtual, and must be defined for all derived classes. 00205 00206 Errors: If memory runs out when trying to copy, then ERROR is called with an out of memory 00207 error and the function returns NULL. 00208 00209 00210 Scope: protected 00211 **********************************************************************************************/ 00212 00213 Node* NodeGrid::SimpleCopy() 00214 { 00215 NodeGrid* NodeCopy = new NodeGrid(); 00216 if (NodeCopy != NULL) 00217 CopyNodeContents(NodeCopy); 00218 return (NodeCopy); 00219 } 00220 00221 /*********************************************************************************************** 00222 > void NodeGrid::CopyNodeContents(NodeGrid* NodeCopy) 00223 00224 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00225 Created: 8/2/94 00226 00227 Inputs: - 00228 Outputs: A copy of this node 00229 00230 Returns: - 00231 00232 Purpose: This method copies the node's contents to the node pointed to by NodeCopy. 00233 00234 Errors: An assertion failure will occur if NodeCopy is NULL 00235 00236 Scope: protected 00237 00238 ***********************************************************************************************/ 00239 00240 00241 void NodeGrid::CopyNodeContents(NodeGrid* NodeCopy) 00242 { 00243 ENSURE(NodeCopy != NULL,"Trying to copy a NodeGridRect's contents to a NULL node"); 00244 00245 NodeRenderablePaper::CopyNodeContents(NodeCopy); 00246 00247 NodeCopy->XOrigin = this->XOrigin; 00248 NodeCopy->YOrigin = this->YOrigin; 00249 NodeCopy->GridColour = this->GridColour; 00250 NodeCopy->GridFlags = this->GridFlags; 00251 00252 for (INT32 i=0;i<NumGridBlobTypes;i++) 00253 NodeCopy->BlobCoords[i] = this->BlobCoords[i]; 00254 } 00255 00256 00257 /*********************************************************************************************** 00258 > void NodeGrid::PolyCopyNodeContents(NodeGrid* pNodeCopy) 00259 00260 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 00261 Created: 18/12/2003 00262 Outputs: - 00263 Purpose: Polymorphically copies the contents of this node to another 00264 Errors: An assertion failure will occur if NodeCopy is NULL 00265 Scope: protected 00266 00267 ***********************************************************************************************/ 00268 00269 void NodeGrid::PolyCopyNodeContents(NodeRenderable* pNodeCopy) 00270 { 00271 ENSURE(pNodeCopy, "Trying to copy a node's contents into a NULL node"); 00272 ENSURE(IS_A(pNodeCopy, NodeGrid), "PolyCopyNodeContents given wrong dest node type"); 00273 00274 if (IS_A(pNodeCopy, NodeGrid)) 00275 CopyNodeContents((NodeGrid*)pNodeCopy); 00276 } 00277 00278 00279 00280 /******************************************************************************************** 00281 00282 > void* NodeGrid::GetDebugDetails(StringBase* Str) 00283 00284 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00285 Created: 8/2/94 00286 Inputs: - 00287 Outputs: Str: String giving debug info about the node 00288 Returns: - 00289 Purpose: For obtaining debug information about the Node 00290 Errors: - 00291 SeeAlso: - 00292 00293 ********************************************************************************************/ 00294 00295 00296 void NodeGrid::GetDebugDetails(StringBase* Str) 00297 { 00298 NodeRenderablePaper::GetDebugDetails(Str); 00299 } 00300 00301 /******************************************************************************************** 00302 00303 > virtual String Describe(BOOL Plural, BOOL Verbose = TRUE) 00304 00305 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00306 Created: 8/2/94 00307 Inputs: Plural: Flag indicating if the string description should be plural or 00308 singular. 00309 Outputs: - 00310 Retuns: Description of the object 00311 Purpose: To return a description of the Node object in either the singular or the 00312 plural. This method is called by the DescribeRange method. 00313 00314 The description will always begin with a lower case letter. 00315 00316 Errors: A resource exception will be thrown if a problem occurs when loading the 00317 string resource. 00318 SeeAlso: - 00319 00320 ********************************************************************************************/ 00321 /* 00322 Technical Notes: 00323 00324 The String resource identifiers should be of the form: ID_<Class>_DescriptionS for the 00325 singular description and ID_<Class>_DescriptionP for the plural. 00326 */ 00327 00328 String NodeGrid::Describe(BOOL /*Plural*/, BOOL /*Verbose*/) 00329 { 00330 ENSURE (FALSE,"The illegal function NodeGrid::Describe was called\n"); 00331 00332 return _T(""); // Just to keep the compiler happy 00333 }; 00334 00335 /*********************************************************************************************** 00336 00337 > virtual void NodeGrid::Render(void) 00338 00339 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00340 Created: 8/2/94 00341 Inputs: RendRegion: Render region to render into 00342 Outputs: - 00343 Returns: - 00344 Purpose: For rendering a node 00345 00346 ***********************************************************************************************/ 00347 00348 void NodeGrid::Render( RenderRegion* /*pRender*/ ) 00349 { 00350 } 00351 00352 /******************************************************************************************** 00353 00354 > BOOL NodeGrid::NeedsToRender(RenderRegion *pRender) 00355 00356 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00357 Created: 25/5/94 00358 Inputs: pRender - A pointer to the current render region (null if none) 00359 Returns: TRUE => This node should be rendered, 00360 FALSE => This node does not need to be rendered. 00361 Purpose: This function will indicate to the caller whether or not 00362 we want to render the given node, according to the information passed in. 00363 SeeAlso: NodeRenderableBounded::NeedsToRender 00364 00365 ********************************************************************************************/ 00366 00367 SubtreeRenderState NodeGrid::RenderSubtree(RenderRegion *pRender, Node** ppNextNode, BOOL bClip) 00368 { 00369 // If no cliprect supplied, assume we do need to render 00370 if (pRender==NULL || !bClip) 00371 return SUBTREE_ROOTANDCHILDREN; 00372 00373 DocRect ClipRect = pRender->GetClipRect(); 00374 00375 return ClipRect.IsIntersectedWith(GridBoundingRect) ? SUBTREE_ROOTANDCHILDREN : SUBTREE_NORENDER; 00376 } 00377 00378 /*********************************************************************************************** 00379 00380 > void NodeGrid::CalcGridRenderSteps(MILLIPOINT PixelWidth,double* pStep,double DomStep,UnitType Units) 00381 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00382 Created: 10/2/94 00383 Inputs: PixelWidth = width of a pixel in millipoints 00384 pStep = reference to resultant render step (IMPORTANT: holds initial step on entry) 00385 DomStep = the number of millipoints between each dominant division 00386 Units = Units used to define the render step 00387 Outputs: 00388 Returns: - 00389 Purpose: Works out what the step value should be used to render the grid with 00390 the give width of a pixel and the given units of the grid. 00391 Errors: 00392 Scope: private 00393 00394 **********************************************************************************************/ 00395 /* Technical note 00396 00397 The following rules have been applied : 00398 00399 1. If the grid points are further apart than MIN_PIX_RENDER_COUNT pixels, then return these values, 00400 i.e. this value will look OK with the given pixel width 00401 2. Otherwise find a grid step that is a multiple of the initial grid step, a factor of the 00402 dominant grid step, and is wider than MIN_PIX_RENDER_COUNT pixels. 00403 00404 */ 00405 00406 void NodeGrid::CalcGridRenderSteps( MILLIPOINT PixelWidth, 00407 double* pStep, // entry = initial step, exit = modified step 00408 double DomStep, // Distance between dominant steps 00409 UnitType Units) // Units of the grid 00410 { 00411 if (Units == NOTYPE) return; // The get-out clause of the recursive contract 00412 00413 double MinRenderWidth = (double)(PixelWidth*MIN_PIX_RENDER_COUNT); // min distance between rendered grid points 00414 00415 if ((DomStep < MinRenderWidth)) 00416 { 00417 double ExtraDomStep = DomStep*::GetUnitMultiple(Units); 00418 CalcGridRenderSteps(PixelWidth,&DomStep,ExtraDomStep,::GetDominantUnit(Units)); 00419 } 00420 00421 double InitialStep = *pStep; 00422 double RenderStep = *pStep; 00423 00424 // Apply the grid step rules to RenderXStep 00425 00426 if (RenderStep < MinRenderWidth) 00427 { 00428 while (RenderStep < MinRenderWidth) 00429 { 00430 do 00431 { 00432 RenderStep += InitialStep; 00433 } while ((mod(DomStep,RenderStep) > (InitialStep/2)) && (RenderStep < DomStep)); 00434 } 00435 } 00436 00437 *pStep = RenderStep; 00438 } 00439 00440 00441 00442 /*********************************************************************************************** 00443 00444 > virtual BOOL NodeGrid::Snap(DocCoord* pDocCoord) 00445 00446 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00447 Created: 8/2/94 00448 Inputs: A DocCoord in Spread coords 00449 Outputs: - 00450 Returns: FALSE - ALWAYS! 00451 Purpose: Place holder for derived classes 00452 SeeAlso: NodeGridRect::Snap 00453 00454 ***********************************************************************************************/ 00455 00456 BOOL NodeGrid::Snap(DocCoord* /*pDocCoord*/) 00457 { 00458 return FALSE; 00459 } 00460 00461 /*********************************************************************************************** 00462 00463 > virtual BOOL NodeGrid::Snap(DocRect* pDocRect,const DocCoord& PrevCoord,const DocCoord& CurCoord); 00464 00465 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00466 Created: 8/2/94 00467 Inputs: A DocRect, and two coords 00468 Outputs: - 00469 Returns: FALSE - ALWAYS! 00470 Purpose: Place holder for derived classes 00471 SeeAlso: NodeGridRect::Snap 00472 00473 ***********************************************************************************************/ 00474 00475 BOOL NodeGrid::Snap(DocRect* /*pDocRect*/,const DocCoord& /*PrevCoord*/,const DocCoord& /*CurCoord*/) 00476 { 00477 return (FALSE); 00478 } 00479 00480 /*********************************************************************************************** 00481 00482 > MILLIPOINT NodeGrid::SnapOrdinate(MILLIPOINT ord,double Step,MILLIPOINT origin) 00483 00484 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00485 Created: 9/3/94 00486 Inputs: ord = the ordinate to snap 00487 Step = distance between each snap point on the line 00488 origin = origin of first snap point of the line 00489 Outputs: 00490 Returns: Snapped version of ord 00491 Purpose: General linear floating point ordinate snapping routine 00492 Errors: BANG! if step = 0 00493 Scope: protected 00494 00495 00496 ***********************************************************************************************/ 00497 00498 MILLIPOINT NodeGrid::SnapOrdinate(MILLIPOINT ord,double Step,MILLIPOINT origin) 00499 { 00500 double fp_ord = ord; 00501 00502 fp_ord -= origin; // Translate to 0 00503 00504 double sign = sgn(fp_ord); // sign = 1 when fp_ord is >=0, sign = -1 when fp_ord<0 00505 00506 fp_ord *= sign; // make +ve if it is -ve 00507 00508 double dist = mod(fp_ord,Step); 00509 if (dist > (Step/2)) dist -= Step; // if closest to min adjacent snap point, snap to it 00510 fp_ord -= dist; 00511 00512 fp_ord += 0.5; // Round up before convertion to MILLIPOINTS, and while still +ve 00513 fp_ord *= sign; // make -ve again if it was -ve on entry 00514 fp_ord += origin; // Translate back to the origin 00515 00516 return (MILLIPOINT)fp_ord; 00517 } 00518 00519 /*********************************************************************************************** 00520 00521 > void NodeGrid::UpdateBlobsData() 00522 00523 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00524 Created: 23/2/94 00525 00526 Inputs: 00527 Outputs: 00528 Returns: 00529 Purpose: Updates the internel select blobs data for the grid. 00530 This involves putting the coords of all the select blobs into the BlobCoords 00531 array of the grid 00532 00533 **********************************************************************************************/ 00534 00535 void NodeGrid::UpdateBlobsData() 00536 { 00537 DocRect& BB = GridBoundingRect; 00538 00539 BlobCoords[BottomLeft] = DocCoord(BB.lo.x,BB.lo.y); 00540 BlobCoords[TopLeft] = DocCoord(BB.lo.x,BB.hi.y); 00541 BlobCoords[TopRight] = DocCoord(BB.hi.x,BB.hi.y); 00542 BlobCoords[BottomRight] = DocCoord(BB.hi.x,BB.lo.y); 00543 00544 MILLIPOINT midX = BB.lo.x+((BB.hi.x-BB.lo.x)/2); 00545 MILLIPOINT midY = BB.lo.y+((BB.hi.y-BB.lo.y)/2); 00546 00547 BlobCoords[LeftMiddle] = DocCoord(BB.lo.x,midY); 00548 BlobCoords[RightMiddle] = DocCoord(BB.hi.x,midY); 00549 BlobCoords[TopMiddle] = DocCoord(midX,BB.hi.y); 00550 BlobCoords[BottomMiddle] = DocCoord(midX,BB.lo.y); 00551 } 00552 00553 /*********************************************************************************************** 00554 00555 > DocCoord NodeGrid::GetBlobCoord(GridBlobType GridBlob) 00556 00557 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00558 Created: 23/2/94 00559 00560 Inputs: The blob type whos coord is required 00561 Outputs: 00562 Returns: The coord of that blob 00563 Purpose: Returns the coord of the required blob of the grid 00564 00565 **********************************************************************************************/ 00566 00567 DocCoord NodeGrid::GetBlobCoord(GridBlobType GridBlob) 00568 { 00569 return BlobCoords[GridBlob]; 00570 } 00571 00572 /*********************************************************************************************** 00573 00574 > void NodeGrid::SetBoundingRect(const DocRect& Rect) 00575 00576 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00577 Created: 23/2/94 00578 Inputs: The bounding rect for grid 00579 Outputs: 00580 Returns: 00581 Purpose: Sets the bounding rect of the grid, plus any other data that is needed. 00582 Should call this after the Node's bounds has been set up using something like 00583 SetInitialBounds. 00584 00585 **********************************************************************************************/ 00586 00587 void NodeGrid::SetBoundingRect(const DocRect& Rect) 00588 { 00589 GridBoundingRect = Rect; 00590 UpdateBlobsData(); 00591 } 00592 00593 /*********************************************************************************************** 00594 00595 > DocRect NodeGrid::GetBoundingRect() 00596 00597 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00598 Created: 23/2/94 00599 Inputs: 00600 Outputs: 00601 Returns: The bounding rect for grid 00602 Purpose: Returns the bounding rect of the grid. 00603 00604 **********************************************************************************************/ 00605 00606 DocRect NodeGrid::GetBoundingRect() 00607 { 00608 return GridBoundingRect; 00609 } 00610 00611 /*********************************************************************************************** 00612 00613 > DocRect NodeGrid::GetBlobBoundingRect() 00614 00615 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00616 Created: 15/3/94 00617 Inputs: 00618 Outputs: 00619 Returns: The blob bounding rect for grid 00620 Purpose: Returns the blob bounding rect of the grid. 00621 00622 **********************************************************************************************/ 00623 00624 DocRect NodeGrid::GetBlobBoundingRect() 00625 { 00626 // Find the paths bounding rectangle 00627 DocRect Rect = GridBoundingRect; 00628 00629 // And if we can find the selected view, add on the size of a selection blob 00630 DocView* pDocView = DocView::GetSelected(); 00631 if ( pDocView != NULL ) 00632 { 00633 DocRect BlobSize; 00634 00635 // Add the size of a blob to the top corner of the bounding rectangle 00636 OSRenderRegion::GetBlobRect(pDocView->GetViewScale(), Rect.HighCorner(), 00637 BT_SELECTEDLARGEST, &BlobSize); 00638 Rect.IncludePoint( BlobSize.HighCorner() ); 00639 00640 // add the size of a blob to the bottom corner of the bounding rectangle 00641 OSRenderRegion::GetBlobRect(pDocView->GetViewScale(), Rect.LowCorner(), 00642 BT_SELECTEDLARGEST, &BlobSize); 00643 Rect.IncludePoint( BlobSize.LowCorner() ); 00644 } 00645 00646 return Rect; 00647 } 00648 00649 /*********************************************************************************************** 00650 00651 > void NodeGrid::SetOrigin(MILLIPOINT X,MILLIPOINT Y) 00652 00653 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00654 Created: 1/3/94 00655 Inputs: The new (X,Y) origin of the grid 00656 Outputs: 00657 Returns: - 00658 Purpose: Used for setting the origin of the grid. 00659 00660 **********************************************************************************************/ 00661 00662 void NodeGrid::SetOrigin(MILLIPOINT X,MILLIPOINT Y) 00663 { 00664 XOrigin = X; 00665 YOrigin = Y; 00666 00667 // a bit of a bodge, but for v1.1 the user origin will be permenently linked to the grid origin 00668 // (during import the grid may not yet be in the tree and has no parent spread - eek!) 00669 Node* pNode = FindParent(); 00670 while (pNode!=NULL && pNode->IsSpread() == FALSE) 00671 pNode = pNode->FindParent(); 00672 if (pNode!=NULL) 00673 ((Spread*)pNode)->SetUserOrigin(DocCoord(X,Y)); 00674 } 00675 00676 00677 /*********************************************************************************************** 00678 00679 > void NodeGrid::GetOrigin(MILLIPOINT* pX,MILLIPOINT* pY) 00680 00681 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00682 Created: 1/3/94 00683 Inputs: Pointers to MILLIPOINT vars. 00684 Outputs: *pX = X Origin of grid 00685 *pY = Y Origin of grid 00686 Returns: - 00687 Purpose: Used for retrieving the origin of the grid. 00688 00689 **********************************************************************************************/ 00690 00691 void NodeGrid::GetOrigin(MILLIPOINT* pX,MILLIPOINT* pY) 00692 { 00693 *pX = XOrigin; 00694 *pY = YOrigin; 00695 } 00696 00697 /*********************************************************************************************** 00698 00699 > BOOL NodeGrid::IsGridSelected() const 00700 00701 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00702 Created: 14/5/94 00703 Inputs: - 00704 Outputs: - 00705 Returns: TRUE if grid is selected 00706 Purpose: Find out if the grid is selected 00707 00708 **********************************************************************************************/ 00709 00710 BOOL NodeGrid::IsGridSelected() const 00711 { 00712 // Grids have their own special selected flag. 00713 return GridFlags.Selected; 00714 } 00715 00716 /*********************************************************************************************** 00717 00718 > void NodeGrid::SetGridSelected(BOOL selected) 00719 00720 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00721 Created: 14/5/94 00722 Inputs: selected - if TRUE, the grid selected flag is set, else it is cleared 00723 Outputs: - 00724 Returns: - 00725 Purpose: Change the grid's selected flag 00726 00727 **********************************************************************************************/ 00728 00729 void NodeGrid::SetGridSelected(BOOL selected) 00730 { 00731 BOOL OldState = GridFlags.Selected; 00732 GridFlags.Selected = selected; 00733 00734 if (OldState != selected) 00735 { 00736 if (selected) 00737 NodeGrid::NumSelected++; 00738 else 00739 NodeGrid::NumSelected--; 00740 } 00741 } 00742 00743 /*********************************************************************************************** 00744 00745 > BOOL NodeGrid::IsDefault() const 00746 00747 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00748 Created: 14/5/94 00749 Inputs: - 00750 Outputs: - 00751 Returns: TRUE if grid is a Default grid 00752 Purpose: Find out if the grid is a Default grid, i.e. one that covers a spread 00753 completely. These behave slightly differently in the selection model 00754 00755 **********************************************************************************************/ 00756 BOOL NodeGrid::IsDefault() const 00757 { 00758 return GridFlags.DefaultGrid; 00759 } 00760 00761 /*********************************************************************************************** 00762 00763 > void NodeGrid::SetDefault(BOOL Default) 00764 00765 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00766 Created: 14/5/94 00767 Inputs: Default - if TRUE, the grid Default flag is set, else it is cleared 00768 Outputs: - 00769 Returns: - 00770 Purpose: Change the grid's Default flag 00771 00772 **********************************************************************************************/ 00773 00774 void NodeGrid::SetDefault(BOOL Default) 00775 { 00776 GridFlags.DefaultGrid = Default; 00777 } 00778 00779 /*********************************************************************************************** 00780 00781 > BOOL NodeGrid::IsDisabled() const 00782 00783 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00784 Created: 14/5/94 00785 Inputs: - 00786 Outputs: - 00787 Returns: TRUE if grid is disabled 00788 Purpose: Find out if the grid is disabled. 00789 A disabled grid does not render and cannot be snapped to. 00790 This mechanism is used to disable Default grids without deleting 00791 them from the tree. 00792 00793 **********************************************************************************************/ 00794 BOOL NodeGrid::IsDisabled() const 00795 { 00796 return GridFlags.Disabled; 00797 } 00798 00799 /*********************************************************************************************** 00800 00801 > void NodeGrid::SetDisabled(BOOL disabled) 00802 00803 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00804 Created: 14/5/94 00805 Inputs: disabled - if TRUE, the grid disabled flag is set, else it is cleared 00806 Outputs: - 00807 Returns: - 00808 Purpose: Change the grid's disabled flag. 00809 Also, if the grid is disabled, its selected flag is cleared as a disabled 00810 grid cannot be selected. 00811 00812 **********************************************************************************************/ 00813 00814 void NodeGrid::SetDisabled(BOOL disabled) 00815 { 00816 GridFlags.Disabled = disabled; 00817 if (disabled) SetGridSelected(FALSE); 00818 } 00819 00820 /*********************************************************************************************** 00821 00822 > static void NodeGrid::RecalcNumSelectedGrids(Spread* pSpread) 00823 00824 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00825 Created: 17/5/94 00826 Inputs: pSpread = ptr to spread that can contain selected grids. 00827 Outputs: - 00828 Returns: - 00829 Purpose: Recalculates the number of selected grids there are in the given spread. 00830 00831 **********************************************************************************************/ 00832 00833 void NodeGrid::RecalcNumSelectedGrids(Spread* pSpread) 00834 { 00835 if (pSpread == NULL) return; 00836 00837 NodeGrid::NumSelected = 0; 00838 NodeGrid::NumNonDefaultSelected = 0; 00839 00840 // Start from the last node in the spread 00841 Node* pNode = pSpread->FindLastChild(); 00842 while (pNode != NULL) 00843 { 00844 if (pNode->IsKindOf(CC_RUNTIME_CLASS(NodeGrid))) 00845 { 00846 NodeGrid* pGrid = (NodeGrid*)pNode; 00847 00848 if (pGrid->IsGridSelected() && !pGrid->IsDisabled()) 00849 { 00850 NodeGrid::NumSelected++; 00851 00852 if (!pGrid->IsDefault()) 00853 NodeGrid::NumNonDefaultSelected++; 00854 } 00855 } 00856 // Scan back along the sibling list 00857 pNode = pNode->FindPrevious(); 00858 } 00859 } 00860 00861 //-------------------------------------------------------------------------------------------- 00862 00863 #ifdef _DEBUG 00864 00865 void NodeGrid::ShowDebugTreeDetails() const 00866 { 00867 NodeRenderablePaper::ShowDebugTreeDetails(); 00868 } 00869 #endif 00870 00871 void NodeGrid::DumpRect(DocRect& R,TCHAR* S) 00872 { 00873 #ifdef _DEBUG 00874 TRACEUSER( "MarkN", _T("%s.lo.x = %ld\n"), S,R.lo.x ); 00875 TRACEUSER( "MarkN", _T("%s.lo.y = %ld\n"), S,R.lo.y); 00876 TRACEUSER( "MarkN", _T("%s.hi.x = %ld\n"), S,R.hi.x); 00877 TRACEUSER( "MarkN", _T("%s.hi.y = %ld\n\n"),S,R.hi.y); 00878 #endif 00879 } 00880 00881 00882 /******************************************************************************************** 00883 > virtual double NodeGrid::CalcDivisions(BOOL Scale) 00884 00885 Author: Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com> 00886 Created: 17/10/95 00887 Inputs: Scale - account for scaling (only FALSE when saving for doc compatibility) 00888 Returns: Number of Units between each main grid point 00889 Purpose: Used to get the number of Units between each main grid point. 00890 Note: No longer uses 'Divisions' as this is a cached value which is not updated when 00891 unit scaling is changed. Dynamically caclulating this overcomes this problem 00892 Divisons has not been removed from the class as it also entails removing all 00893 code setting the value. I have proposed the whole system needs revamping! 00894 ********************************************************************************************/ 00895 00896 double NodeGrid::CalcDivisions(BOOL Scale) 00897 { 00898 double Spacing = GetMainStep(); 00899 UnitType Units = GetUnits(Scale); 00900 BOOL ok = TRUE; 00901 String_256 Str; 00902 00903 if (Scale==FALSE) 00904 ok = Convert::MillipointsToString(Spacing,Units,&Str,10); 00905 else 00906 { 00907 DimScale* pDimScale = DimScale::GetPtrDimScale(this); 00908 ERROR2IF(pDimScale==NULL,FALSE,"NodeGridRect::CalcDivisions() - pDimScale==NULL"); 00909 ok = pDimScale->ConvertToUnits(Spacing,&Str,TRUE,10,Units); 00910 } 00911 00912 double Divs; 00913 UnitType DummyUnits; 00914 if (ok) ok=Convert::StringToComponents(Str, &Divs, &DummyUnits); 00915 if (!ok) Divs=1; 00916 00917 return Divs; 00918 } 00919 00920 00921 //-------------------------------------------------------------------------------------------- 00922 //-------------------------------------------------------------------------------------------- 00923 00924 // NodeGridRect methods 00925 00926 CC_IMPLEMENT_DYNAMIC(NodeGridRect, NodeGrid) 00927 00928 /********************************************************************************************* 00929 00930 > NodeGridRect::NodeGridRect() 00931 00932 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00933 Created: 8/2/94 00934 Inputs: - 00935 Outputs: 00936 Returns: - 00937 00938 Purpose: This constructor creates a NodeGridRect linked to no other nodes, with all status 00939 flags false, and NULL bounding and pasteboard rectangles. 00940 00941 Errors: 00942 00943 **********************************************************************************************/ 00944 00945 00946 NodeGridRect::NodeGridRect(): NodeGrid() 00947 { 00948 Units = INCHES; 00949 Divisions = 1.0; 00950 Subdivisions= 2; 00951 00952 MainXStep = 72000.0; 00953 SubXStep = MainXStep/Subdivisions; 00954 MainYStep = MainXStep; 00955 SubYStep = SubXStep; 00956 } 00957 00958 00959 /******************************************************************************************** 00960 00961 > String NodeGridRect::Describe(BOOL Plural, BOOL Verbose = TRUE) 00962 00963 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00964 Created: 8/2/94 00965 Inputs: Plural: Flag indicating if the string description should be plural or 00966 singular. 00967 Outputs: - 00968 Retuns: Description of the object 00969 Purpose: To return a description of the Node object in either the singular or the 00970 plural. This method is called by the DescribeRange method. 00971 00972 The description will always begin with a lower case letter. 00973 00974 Errors: A resource exception will be thrown if a problem occurs when loading the 00975 string resource. 00976 SeeAlso: - 00977 00978 ********************************************************************************************/ 00979 /* 00980 Technical Notes: 00981 00982 The String resource identifiers should be of the form: ID_<Class>_DescriptionS for the 00983 singular description and ID_<Class>_DescriptionP for the plural. 00984 */ 00985 00986 String NodeGridRect::Describe(BOOL Plural, BOOL Verbose) 00987 { 00988 00989 if (Plural) 00990 return (String(_R(IDS_GRIDRECT_DESCRP))); 00991 else 00992 return (String(_R(IDS_GRIDRECT_DESCRS))); 00993 }; 00994 00995 00996 /*********************************************************************************************** 00997 00998 > void NodeGridRect::Render(RenderRegion* pRender) 00999 01000 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 01001 Created: 8/2/94 01002 Inputs: pRender = a render region 01003 Outputs: - 01004 Returns: - 01005 Purpose: Renders the rectangular grid item 01006 01007 Errors: - 01008 SeeAlso: - 01009 01010 ***********************************************************************************************/ 01011 01012 void NodeGridRect::Render( RenderRegion* pRender ) 01013 { 01014 #if !defined(EXCLUDE_FROM_RALPH) 01015 // static INT32 bbb=0; 01016 // if (IsUserName("MarkN")) TRACE( _T("\n-------------------------------------------------------------------\n")); 01017 // if (IsUserName("MarkN")) TRACE( _T("NodeGridRect::Render - %ld\n\n"),bbb++); 01018 01019 // See if the render region likes grids to be drawn.... 01020 if (!pRender->WantsGrids()) 01021 return; 01022 01023 // If the grid is disabled, don't bother either 01024 if (IsDisabled()) 01025 return; 01026 01027 View* pView = pRender->GetRenderView(); 01028 if ((pView == NULL) || (!IS_A(pView, DocView))) 01029 // No docview to render to. 01030 return; 01031 01032 DocView *pDocView = (DocView *) pView; 01033 01034 if (!pDocView->GetShowGridState() && Tool::GetCurrentID() != TOOLID_GRID) return; 01035 01036 // Set up attributes for drawing grid points 01037 pRender->SaveContext(); 01038 // Don't set line attributes because grid points are now plotted used filled rects 01039 // pRender->SetLineWidth(0); // Means single-pixel lines 01040 // pRender->SetLineColour(GridColour); // Grid blobs are in this colour 01041 01042 // Set fill attributes for grid point rectangle plotting... 01043 pRender->SetLineWidth(0); 01044 pRender->SetLineColour(COLOUR_TRANS); 01045 pRender->SetFillColour(GridColour); 01046 01047 DocRect ClipRect = pRender->GetClipRect(); // Get the current clip rect 01048 DocRect RendRect; 01049 01050 RendRect.lo.x = max(GridBoundingRect.lo.x,ClipRect.lo.x); // hi and lo renderable grid points 01051 RendRect.lo.y = max(GridBoundingRect.lo.y,ClipRect.lo.y); // derived from the clip rect and the 01052 RendRect.hi.x = min(GridBoundingRect.hi.x,ClipRect.hi.x); // node's bounding rect 01053 RendRect.hi.y = min(GridBoundingRect.hi.y,ClipRect.hi.y); 01054 01055 if (RendRect.IsValid()) 01056 { 01057 MILLIPOINT PixelWidth = pRender->GetScaledPixelWidth(); // the width of a single pixel 01058 01059 RenderMainPoints(pRender,RendRect,PixelWidth); // Render the main grid points (crosshairs) 01060 RenderSubPoints(pRender,RendRect,PixelWidth); // Render the sub grid points (dots) 01061 } 01062 01063 pRender->RestoreContext(); 01064 #endif 01065 } 01066 01067 /*********************************************************************************************** 01068 01069 > void NodeGridRect::RenderMainPoints(RenderRegion* pRender,DocRect RendRect,MILLIPOINT PixelWidth) 01070 01071 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 01072 Created: 9/2/94 01073 01074 Inputs: pRender = region to render to 01075 RendRect = Rectangle defining the renderable portion of the grid 01076 PixelWidth = width of a pixel in millipoints 01077 Outputs: 01078 Returns: 01079 Purpose: Renders the main grid points within the given renderable rectangle 01080 Errors: 01081 Scope: private 01082 01083 ***********************************************************************************************/ 01084 01085 void NodeGridRect::RenderMainPoints(RenderRegion* pRender,DocRect RendRect,MILLIPOINT PixelWidth) 01086 { 01087 #if !defined(EXCLUDE_FROM_RALPH) 01088 // Set the fp render step values to be the underlying main grid step value 01089 double fp_RenderXStep = MainXStep; 01090 double fp_RenderYStep = MainYStep; 01091 01092 // Calculate the step for rendering the grid in relation to the width of a pixel and the 01093 // factors of the dominant unit 01094 CalcGridRenderSteps(PixelWidth,&fp_RenderXStep,fp_RenderXStep*::GetUnitMultiple(Units),Units); 01095 CalcGridRenderSteps(PixelWidth,&fp_RenderYStep,fp_RenderYStep*::GetUnitMultiple(Units),Units); 01096 01097 // Snap the render rect to these adjusted steps so we render all points within the renderable 01098 // portion of the grid 01099 Snap(&RendRect.lo,fp_RenderXStep,fp_RenderYStep); 01100 Snap(&RendRect.hi,fp_RenderXStep,fp_RenderYStep); 01101 01102 ENSURE(RendRect.IsValid(),"RendRect is invalid in NodeGridRect::RenderMainPoints"); 01103 01104 // Get fixed point versions of the fp values for speedy grid rendering 01105 MILLIPOINT RenderXStep = (MILLIPOINT)((fp_RenderXStep * GRID_REND_FACTOR)+0.5); 01106 MILLIPOINT RenderYStep = (MILLIPOINT)((fp_RenderYStep * GRID_REND_FACTOR)+0.5); 01107 01108 // DumpRect(RendRect,"RendRect"); 01109 01110 // Convert RendRect to fixed point values 01111 RendRect.lo.x *= GRID_REND_FACTOR; 01112 RendRect.lo.y *= GRID_REND_FACTOR; 01113 RendRect.hi.x *= GRID_REND_FACTOR; 01114 RendRect.hi.y *= GRID_REND_FACTOR; 01115 01116 DocRect ScaledBB = GridBoundingRect; 01117 ScaledBB.lo.x *= GRID_REND_FACTOR; 01118 ScaledBB.lo.y *= GRID_REND_FACTOR; 01119 ScaledBB.hi.x *= GRID_REND_FACTOR; 01120 ScaledBB.hi.y *= GRID_REND_FACTOR; 01121 01122 // Make sure the render rectangle region doesn't lie outside the bounding rect 01123 while (RendRect.lo.x < ScaledBB.lo.x) RendRect.lo.x += RenderXStep; 01124 while (RendRect.lo.y < ScaledBB.lo.y) RendRect.lo.y += RenderYStep; 01125 while (RendRect.hi.x >= ScaledBB.hi.x) RendRect.hi.x -= RenderXStep; 01126 while (RendRect.hi.y >= ScaledBB.hi.y) RendRect.hi.y -= RenderYStep; 01127 01128 RendRect.hi.x += GRID_REND_FACTOR; // compensate for errors (i.e. add the bodge factor) 01129 RendRect.hi.y += GRID_REND_FACTOR; // compensate for errors 01130 01131 // Render those grid points boy! 01132 01133 DocCoord GridPoint,TrueGridPoint; 01134 01135 const MILLIPOINT Pix = pRender->GetScaledPixelWidth(); 01136 // const MILLIPOINT PixBy2 = Pix/2; 01137 const MILLIPOINT Length = PIX_CROSSHAIR_SIZE * Pix; 01138 01139 for (GridPoint.x=RendRect.lo.x;GridPoint.x<=RendRect.hi.x;GridPoint.x+=RenderXStep) 01140 { 01141 for (GridPoint.y=RendRect.lo.y;GridPoint.y<=RendRect.hi.y;GridPoint.y+=RenderYStep) 01142 { 01143 // Scale the fixed point grid coord down to get the true coord of the grid point 01144 TrueGridPoint.x = (GridPoint.x+(GRID_REND_FACTOR/2)) / GRID_REND_FACTOR; 01145 TrueGridPoint.y = (GridPoint.y+(GRID_REND_FACTOR/2)) / GRID_REND_FACTOR; 01146 01147 // pRender->DrawCross(TrueGridPoint, PIX_CROSSHAIR_SIZE); 01148 // Phil says: Don't use DrawPixel because it can't be trusted to plot the 01149 // same pixel under GDI as it does under GDraw! 01150 // Instead draw two rectangles centered around the required coord. 01151 DocRect Horz(TrueGridPoint.x-Length,TrueGridPoint.y,TrueGridPoint.x+Length+Pix,TrueGridPoint.y+Pix); 01152 pRender->DrawRect(&Horz); 01153 01154 DocRect Vert(TrueGridPoint.x,TrueGridPoint.y-Length,TrueGridPoint.x+Pix,TrueGridPoint.y+Length+Pix); 01155 pRender->DrawRect(&Vert); 01156 01157 } 01158 } 01159 #endif 01160 } 01161 01162 01163 /*********************************************************************************************** 01164 01165 > void NodeGridRect::RenderSubPoints(RenderRegion* pRender,DocRect RendRect,MILLIPOINT PixelWidth) 01166 01167 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 01168 Created: 9/2/94 01169 01170 Inputs: pRender = region to render to 01171 RendRect = Rectangle defining the renderable portion of the grid 01172 PixelWidth = width of a pixel in millipoints 01173 Outputs: 01174 Returns: 01175 Purpose: Renders the sub grid points within the given renderable rectangle 01176 Errors: 01177 Scope: private 01178 01179 ***********************************************************************************************/ 01180 01181 void NodeGridRect::RenderSubPoints(RenderRegion* pRender,DocRect RendRect,MILLIPOINT PixelWidth) 01182 { 01183 #if !defined(EXCLUDE_FROM_RALPH) 01184 // Set the fp render step values to be the underlying sub grid step value 01185 double fp_RenderXStep = SubXStep; 01186 double fp_RenderYStep = SubYStep; 01187 01188 // Calculate the step for rendering the grid in relation to the width of a pixel and the 01189 // factors of the dominant unit 01190 CalcGridRenderSteps(PixelWidth,&fp_RenderXStep,MainXStep,Units); 01191 CalcGridRenderSteps(PixelWidth,&fp_RenderYStep,MainYStep,Units); 01192 01193 // If the render step is greater than the main step then don't render the sub grid 01194 if (fp_RenderXStep >= MainXStep) return; 01195 if (fp_RenderYStep >= MainYStep) return; 01196 01197 // Snap the render rect to the render steps so we render all points within the renderable 01198 // portion of the grid 01199 01200 Snap(&RendRect.lo,fp_RenderXStep,fp_RenderYStep); 01201 Snap(&RendRect.hi,fp_RenderXStep,fp_RenderYStep); 01202 01203 ENSURE(RendRect.IsValid(),"RendRect is invalid in NodeGridRect::RenderSubPoints"); 01204 01205 // Get fixed point versions of the fp values for speedy grid rendering 01206 MILLIPOINT RenderXStep = (MILLIPOINT)((fp_RenderXStep * GRID_REND_FACTOR)+0.5); 01207 MILLIPOINT RenderYStep = (MILLIPOINT)((fp_RenderYStep * GRID_REND_FACTOR)+0.5); 01208 01209 // Convert RendRect to fixed point values 01210 RendRect.lo.x *= GRID_REND_FACTOR; 01211 RendRect.lo.y *= GRID_REND_FACTOR; 01212 RendRect.hi.x *= GRID_REND_FACTOR; 01213 RendRect.hi.y *= GRID_REND_FACTOR; 01214 01215 DocRect ScaledBB = GridBoundingRect; 01216 ScaledBB.lo.x *= GRID_REND_FACTOR; 01217 ScaledBB.lo.y *= GRID_REND_FACTOR; 01218 ScaledBB.hi.x *= GRID_REND_FACTOR; 01219 ScaledBB.hi.y *= GRID_REND_FACTOR; 01220 01221 // Make sure the render rectangle region doesn't lie outside the bounding rect 01222 while (RendRect.lo.x < ScaledBB.lo.x) RendRect.lo.x += RenderXStep; 01223 while (RendRect.lo.y < ScaledBB.lo.y) RendRect.lo.y += RenderYStep; 01224 while (RendRect.hi.x >= ScaledBB.hi.x) RendRect.hi.x -= RenderXStep; 01225 while (RendRect.hi.y >= ScaledBB.hi.y) RendRect.hi.y -= RenderYStep; 01226 01227 RendRect.hi.x += GRID_REND_FACTOR; // compensate for errors (i.e. add the bodge factor) 01228 RendRect.hi.y += GRID_REND_FACTOR; // compensate for errors 01229 01230 // Go ahead punk, render those points 01231 01232 DocCoord GridPoint,TrueGridPoint; 01233 01234 const MILLIPOINT Pix = pRender->GetScaledPixelWidth(); 01235 // const MILLIPOINT PixBy2 = Pix/2; 01236 01237 for (GridPoint.x=RendRect.lo.x;GridPoint.x<=RendRect.hi.x;GridPoint.x+=RenderXStep) 01238 { 01239 for (GridPoint.y=RendRect.lo.y;GridPoint.y<=RendRect.hi.y;GridPoint.y+=RenderYStep) 01240 { 01241 // Scale the fixed point grid coord down to get the true coord of the grid point 01242 TrueGridPoint.x = (GridPoint.x+(GRID_REND_FACTOR/2)) / GRID_REND_FACTOR; 01243 TrueGridPoint.y = (GridPoint.y+(GRID_REND_FACTOR/2)) / GRID_REND_FACTOR; 01244 01245 // pRender->DrawPixel(TrueGridPoint); 01246 // Phil says: Don't use DrawPixel because it can't be trusted to plot the 01247 // same pixel under GDI as it does under GDraw! 01248 // Instead draw a rectangle 1*1 pixels around the required coord. 01249 DocRect Pixel( TrueGridPoint.x, 01250 TrueGridPoint.y, 01251 TrueGridPoint.x+Pix, 01252 TrueGridPoint.y+Pix); 01253 pRender->DrawRect(&Pixel); 01254 } 01255 } 01256 #endif 01257 } 01258 01259 /*********************************************************************************************** 01260 01261 > BOOL NodeGridRect::Snap(DocCoord* pDocCoord) 01262 01263 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 01264 Created: 9/2/94 01265 Inputs: pDocCoord = a coord in Spread coords 01266 Outputs: 01267 Returns: TRUE - the DocCoord has been snapped to the grid. 01268 FALSE - the DocCoord has not been processed. 01269 01270 Purpose: Snaps to given coord to the nearest grid point. If it is not appropriate to snap 01271 the coord to the grid (at the moment this means the coord lies outside the grid object's 01272 bounding box), then FALSE is returned. 01273 Errors: 01274 Scope: public 01275 01276 **********************************************************************************************/ 01277 01278 BOOL NodeGridRect::Snap(DocCoord* pDocCoord) 01279 { 01280 if (IsDisabled()) return FALSE; 01281 01282 ENSURE(SubXStep !=0,"SubXStep ==0 in NodeGridRect::Snap"); 01283 ENSURE(SubYStep !=0,"SubYStep ==0 in NodeGridRect::Snap"); 01284 01285 if (!GridBoundingRect.ContainsCoord(DocCoord(pDocCoord->x,pDocCoord->y))) 01286 return (FALSE); 01287 01288 MILLIPOINT x = SnapOrdinate(pDocCoord->x,SubXStep,XOrigin); 01289 MILLIPOINT y = SnapOrdinate(pDocCoord->y,SubYStep,YOrigin); 01290 01291 if (!GridBoundingRect.ContainsCoord(DocCoord(x,y))) 01292 return (FALSE); 01293 01294 pDocCoord->x = x; 01295 pDocCoord->y = y; 01296 01297 return (TRUE); 01298 } 01299 01300 /*********************************************************************************************** 01301 01302 > BOOL NodeGridRect::Snap(DocRect* pDocRect,const DocCoord& PrevCoord,const DocCoord& CurCoord) 01303 01304 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 01305 Created: 9/2/94 01306 Inputs: pDocCoord - the rectangle to snap 01307 StartDrag - Start coord of drag 01308 EndDrag - End coord of drag 01309 Outputs: 01310 Returns: TRUE - the DocRect been snapped to the grid. 01311 FALSE - the DocRect has not been processed. 01312 01313 Purpose: Snaps the given rect to the nearest position on the grid, preserving its width 01314 and height. 01315 The coords of the rect used for the snapping are determined by the PrevCoord and 01316 CurCoord coords supplied. This is done to allow the user to control how a 01317 selection rectangle is snapped to the grid by the direction of his/her last mouse 01318 movement. 01319 To force the bottom left hand corner of the rect to be snapped, 01320 supply PrevCoord=(0,0) and CurCoord(-1,-1). 01321 Scope: public 01322 01323 **********************************************************************************************/ 01324 01325 BOOL NodeGridRect::Snap(DocRect* pDocRect,const DocCoord& PrevCoord,const DocCoord& CurCoord) 01326 { 01327 if (IsDisabled()) return FALSE; 01328 01329 ENSURE(SubXStep !=0,"SubXStep ==0 in NodeGridRect::Snap"); 01330 ENSURE(SubYStep !=0,"SubYStep ==0 in NodeGridRect::Snap"); 01331 01332 INT32 xdir = CurCoord.x - PrevCoord.x; 01333 INT32 ydir = CurCoord.y - PrevCoord.y; 01334 INT32 x,y,prevx, prevy; 01335 01336 if (LastXDir == 0) LastXDir = xdir; 01337 if (xdir == 0) xdir = LastXDir; 01338 LastXDir = xdir; 01339 01340 if (xdir <= 0) x = pDocRect->lo.x; else x = pDocRect->hi.x; 01341 01342 if (LastYDir == 0) LastYDir = ydir; 01343 if (ydir == 0) ydir = LastYDir; 01344 LastYDir = ydir; 01345 01346 if (ydir <= 0) y = pDocRect->lo.y; else y = pDocRect->hi.y; 01347 01348 if (!GridBoundingRect.ContainsCoord(DocCoord(x,y))) 01349 return (FALSE); 01350 01351 prevx = x; 01352 prevy = y; 01353 x = SnapOrdinate(x,SubXStep,XOrigin); 01354 y = SnapOrdinate(y,SubYStep,YOrigin); 01355 01356 if (!GridBoundingRect.ContainsCoord(DocCoord(x,y))) 01357 return (FALSE); 01358 01359 pDocRect->Translate(x-prevx,y-prevy); 01360 01361 return (TRUE); 01362 } 01363 /*********************************************************************************************** 01364 01365 > BOOL NodeGridRect::Snap(DocCoord* pDocCoord,double XStep,double YStep) 01366 01367 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 01368 Created: 9/2/94 01369 Inputs: pDocCoord - the coord to snap 01370 XStep - the x step to use when snapping the point 01371 YStep - the y step to use when snapping the point 01372 Outputs: 01373 Returns: TRUE - the DocCoord has been snapped to the grid. 01374 FALSE - the DocCoord has not been processed. 01375 01376 Purpose: Same as Snap(pDocCoord), except the coord is snapped to grid points at the given intervals 01377 Errors: 01378 Scope: public 01379 01380 **********************************************************************************************/ 01381 01382 BOOL NodeGridRect::Snap(DocCoord* pDocCoord,double XStep,double YStep) 01383 { 01384 if (IsDisabled()) return FALSE; 01385 01386 ENSURE(XStep!=0,"XStep==0 in NodeGridRect::Snap(pDocCoord,XStep,YStep"); 01387 ENSURE(YStep!=0,"YStep==0 in NodeGridRect::Snap(pDocCoord,XStep,YStep"); 01388 01389 pDocCoord->x = SnapOrdinate(pDocCoord->x,XStep,XOrigin); 01390 pDocCoord->y = SnapOrdinate(pDocCoord->y,YStep,YOrigin); 01391 01392 return (TRUE); 01393 } 01394 01395 01396 /*********************************************************************************************** 01397 01398 > Node* NodeGridRect::SimpleCopy() // Private method 01399 01400 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 01401 Created: 8/2/94 01402 01403 Inputs: - 01404 Outputs: 01405 Returns: A copy of the node, or NULL if memory runs out 01406 01407 Purpose: This method returns a shallow copy of the node with all Node pointers NULL. 01408 The function is virtual, and must be defined for all derived classes. 01409 01410 Errors: If memory runs out when trying to copy, then ERROR is called with an out of memory 01411 error and the function returns NULL. 01412 01413 01414 Scope: protected 01415 **********************************************************************************************/ 01416 01417 Node* NodeGridRect::SimpleCopy() 01418 { 01419 NodeGridRect* NodeCopy = new NodeGridRect(); 01420 if (NodeCopy != NULL) 01421 CopyNodeContents(NodeCopy); 01422 return (NodeCopy); 01423 } 01424 01425 /*********************************************************************************************** 01426 > void NodeGridRect::CopyNodeContents(NodeGridRect* NodeCopy) 01427 01428 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 01429 Created: 8/2/94 01430 01431 Inputs: - 01432 Outputs: A copy of this node 01433 01434 Returns: - 01435 01436 Purpose: This method copies the node's contents to the node pointed to by NodeCopy. 01437 01438 Errors: An assertion failure will occur if NodeCopy is NULL 01439 01440 Scope: protected 01441 01442 ***********************************************************************************************/ 01443 01444 01445 void NodeGridRect::CopyNodeContents(NodeGridRect* NodeCopy) 01446 { 01447 ENSURE(NodeCopy != NULL,"Trying to copy a NodeGridRect's contents to a NULL node"); 01448 NodeGrid::CopyNodeContents(NodeCopy); 01449 01450 NodeCopy->MainXStep = this->MainXStep; 01451 NodeCopy->MainYStep = this->MainYStep; 01452 NodeCopy->SubXStep = this->SubXStep; 01453 NodeCopy->SubYStep = this->SubYStep; 01454 01455 NodeCopy->Units = this->Units; 01456 NodeCopy->Divisions = this->Divisions; 01457 NodeCopy->Subdivisions = this->Subdivisions; 01458 } 01459 01460 01461 /*********************************************************************************************** 01462 > void NodeGridRect::PolyCopyNodeContents(NodeRenderable* pNodeCopy) 01463 01464 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 01465 Created: 18/12/2003 01466 Outputs: - 01467 Purpose: Polymorphically copies the contents of this node to another 01468 Errors: An assertion failure will occur if NodeCopy is NULL 01469 Scope: protected 01470 01471 ***********************************************************************************************/ 01472 01473 void NodeGridRect::PolyCopyNodeContents(NodeRenderable* pNodeCopy) 01474 { 01475 ENSURE(pNodeCopy, "Trying to copy a node's contents into a NULL node"); 01476 ENSURE(IS_A(pNodeCopy, NodeGridRect), "PolyCopyNodeContents given wrong dest node type"); 01477 01478 if (IS_A(pNodeCopy, NodeGridRect)) 01479 CopyNodeContents((NodeGridRect*)pNodeCopy); 01480 } 01481 01482 01483 01484 /******************************************************************************************** 01485 01486 > void* NodeGridRect::GetDebugDetails(StringBase* Str) 01487 01488 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 01489 Created: 8/2/94 01490 Inputs: - 01491 Outputs: Str: String giving debug info about the node 01492 Returns: - 01493 Purpose: For obtaining debug information about the Node 01494 Errors: - 01495 SeeAlso: - 01496 01497 ********************************************************************************************/ 01498 01499 01500 void NodeGridRect::GetDebugDetails(StringBase* Str) 01501 { 01502 NodeGrid::GetDebugDetails(Str); 01503 } 01504 01505 01506 //-------------------------------------------------------------------------------------------- 01507 01508 #ifdef _DEBUG 01509 01510 void NodeGridRect::ShowDebugTreeDetails() const 01511 { 01512 TRACE( _T("NodeGridRect::ShowDebugTreeDetails() ")); 01513 Node::ShowDebugTreeDetails(); 01514 } 01515 01516 #endif 01517 01518 //-------------------------------------------------------------------------------------------- 01519 01520 /******************************************************************************************** 01521 > BOOL NodeGridRect::SetGridParams(double Div,UINT32 Subdiv,UnitType NewUnits, BOOL Scale=TRUE) 01522 01523 Author: Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com> 01524 Created: 16/10/95 01525 Inputs: Div - Number of Units between each main grid point 01526 Subdiv - Number of subdivisions between each main grid point 01527 NewUnits - The units the grid is defined in 01528 Scale - account for unit scaling (only FALSE when loading for compatibility with old docs) 01529 Returns: FALSE if fails 01530 Purpose: Defines the grid. 01531 ********************************************************************************************/ 01532 01533 BOOL NodeGridRect::SetGridParams(double Div, UINT32 Subdiv, UnitType NewUnits, BOOL Scale) 01534 { 01535 if (Div < 0) 01536 { 01537 ERROR3("NodeGridRect::SetGridParams() - Div < 0!"); 01538 Div = 0.0; 01539 } 01540 if (Subdiv < 1) 01541 { 01542 ERROR3("NodeGridRect::SetGridParams() - SubDiv < 1!"); 01543 Subdiv = 1; 01544 } 01545 01546 DimScale* pDimScale = DimScale::GetPtrDimScale(this); 01547 ERROR2IF(pDimScale==NULL,FALSE,"NodeGridRect::SetGridParams() - pDimScale==NULL"); 01548 01549 // set the raw values in the grid - but only set units if scaling turned off 01550 // (except if scaling is not to be accounted for - ie during loading for compatibility with old docs - yuk!) 01551 Divisions = Div; 01552 Subdivisions = Subdiv; 01553 if (Scale==FALSE || pDimScale->GetScaleUnits()==NOTYPE) 01554 Units = NewUnits; 01555 01556 // convert the divisions and units into a millipoint grid spacing (accounting for unit scaling) - yuk! 01557 double GridSpacing=0; 01558 if (Scale) 01559 { 01560 BOOL ok = pDimScale->ComponentsToMillipoint(&GridSpacing, Divisions, GetUnits()); 01561 if (!ok) return FALSE; 01562 } 01563 else 01564 { 01565 DocUnitList* pDocUnitList = DocUnitList::GetCurrentDocUnitList(); 01566 ERROR2IF(pDocUnitList==NULL,FALSE,"DimScale::ComponentsToMillipoint() - pDocUnitList==NULL"); 01567 Unit* pUnit = pDocUnitList->FindUnit(Units); 01568 ERROR2IF(pUnit==NULL,FALSE,"DimScale::ComponentsToMillipoint() - pUnit==NULL"); 01569 GridSpacing = Div * pUnit->GetMillipoints(); 01570 } 01571 01572 if (GridSpacing<1) 01573 { 01574 ERROR3("NodeGridRect::SetGridParams() - GridSpacing < 1!"); 01575 GridSpacing=1; 01576 } 01577 01578 MainXStep = GridSpacing; 01579 SubXStep = MainXStep/Subdivisions; 01580 if (SubXStep<1) 01581 { 01582 ERROR3("NodeGridRect::SetGridParams() - SubXStep < 1!"); 01583 SubXStep=1; 01584 } 01585 01586 MainYStep = MainXStep; 01587 SubYStep = SubXStep; 01588 01589 return TRUE; 01590 } 01591 01592 01593 /******************************************************************************************** 01594 > double NodeGridRect::GetDivisions(BOOL Scale=TRUE) 01595 01596 Author: Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com> 01597 Created: 17/10/95 01598 Inputs: Scale - account for scaling (only FALSE when saving for doc compatibility) 01599 Returns: Number of Units between each main grid point 01600 Purpose: Used to get the number of Units between each main grid point. 01601 ********************************************************************************************/ 01602 01603 double NodeGridRect::GetDivisions(BOOL Scale) 01604 { 01605 return NodeGrid::CalcDivisions(Scale); 01606 } 01607 01608 01609 /******************************************************************************************** 01610 01611 > UINT32 NodeGridRect::GetSubdivisions() 01612 01613 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 01614 Created: 1/3/94 01615 Inputs: - 01616 Outputs: - 01617 Returns: Num subdivisions 01618 Purpose: Used to get the number of subdivisions between each main grid point. 01619 Errors: - 01620 SeeAlso: - 01621 01622 ********************************************************************************************/ 01623 01624 UINT32 NodeGridRect::GetSubdivisions() 01625 { 01626 return Subdivisions; 01627 } 01628 01629 01630 /******************************************************************************************** 01631 > UnitType NodeGridRect::GetUnits(BOOL Scale=TRUE) 01632 01633 Author: Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com> 01634 Created: 20/10/95 01635 Inputs: Scale - account for unit scaling (only FALSE when saving for compatibility with old docs) 01636 Returns: Units used by the grid 01637 Purpose: Gets the units used by the grid 01638 ********************************************************************************************/ 01639 01640 UnitType NodeGridRect::GetUnits(BOOL Scale) 01641 { 01642 DimScale* pDimScale = DimScale::GetPtrDimScale(this); 01643 ERROR2IF(pDimScale==NULL,NOTYPE,"NodeGridRect::GetUnits() - pDimScale==NULL"); 01644 01645 // if scaling turned on return scale units 01646 // (except if scaling is not to be accounted for - ie during saving for compatibility with old docs) 01647 UnitType ScaleUnits = pDimScale->GetScaleUnits(); 01648 if (Scale && ScaleUnits!=NOTYPE) 01649 return ScaleUnits; 01650 01651 return Units; 01652 } 01653 01654 01655 //-------------------------------------------------------------------------------------------- 01656 //-------------------------------------------------------------------------------------------- 01657 01658 // NodeGridIso methods 01659 01660 CC_IMPLEMENT_DYNAMIC(NodeGridIso, NodeGrid) 01661 01662 /********************************************************************************************* 01663 01664 > NodeGridRect::NodeGridIso() 01665 01666 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 01667 Created: 15/2/94 01668 Inputs: - 01669 Outputs: 01670 Returns: - 01671 01672 Purpose: This constructor creates a NodeGridIso linked to no other nodes, with all status 01673 flags false, and NULL bounding and pasteboard rectangles. 01674 01675 Errors: 01676 01677 **********************************************************************************************/ 01678 01679 01680 NodeGridIso::NodeGridIso(): NodeGrid() 01681 { 01682 Units = INCHES; 01683 Divisions = 1.0; 01684 Subdivisions = 4; 01685 01686 MainStep = 72000.0; 01687 SubStep = MainStep/Subdivisions; 01688 } 01689 01690 01691 /******************************************************************************************** 01692 01693 > String NodeGridIso::Describe(BOOL Plural, BOOL Verbose = TRUE) 01694 01695 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 01696 Created: 15/2/94 01697 Inputs: Plural: Flag indicating if the string description should be plural or 01698 singular. 01699 Outputs: - 01700 Retuns: Description of the object 01701 Purpose: To return a description of the Node object in either the singular or the 01702 plural. This method is called by the DescribeRange method. 01703 01704 The description will always begin with a lower case letter. 01705 01706 Errors: A resource exception will be thrown if a problem occurs when loading the 01707 string resource. 01708 SeeAlso: - 01709 01710 ********************************************************************************************/ 01711 /* 01712 Technical Notes: 01713 01714 The String resource identifiers should be of the form: ID_<Class>_DescriptionS for the 01715 singular description and ID_<Class>_DescriptionP for the plural. 01716 */ 01717 01718 String NodeGridIso::Describe(BOOL Plural, BOOL Verbose) 01719 { 01720 if (Plural) 01721 return (String(_R(IDS_GRIDISO_DESCRP))); 01722 else 01723 return (String(_R(IDS_GRIDISO_DESCRS))); 01724 }; 01725 01726 01727 /*********************************************************************************************** 01728 01729 > void NodeGridIso::Render(RenderRegion* pRender) 01730 01731 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 01732 Created: 15/2/94 01733 Inputs: pRender = a render region 01734 Outputs: - 01735 Returns: - 01736 Purpose: Renders the isometric grid item 01737 01738 Errors: - 01739 SeeAlso: - 01740 01741 ***********************************************************************************************/ 01742 01743 void NodeGridIso::Render( RenderRegion* pRender ) 01744 { 01745 #if !defined(EXCLUDE_FROM_RALPH) 01746 if (IsDisabled()) return; 01747 01748 View* pView = pRender->GetRenderView(); 01749 if ((pView == NULL) || (!IS_A(pView, DocView))) 01750 // No docview to render to. 01751 return; 01752 01753 DocView *pDocView = (DocView *) pView; 01754 01755 if (!pDocView->GetShowGridState() && Tool::GetCurrentID() != TOOLID_GRID) return; 01756 01757 // Set up attributes for drawing grid points 01758 pRender->SaveContext(); 01759 // Don't setup for line rendering because grid points now rendered as filled rects... 01760 // pRender->SetLineWidth(0); // Means single-pixel lines 01761 // pRender->SetLineColour(GridColour); // Grid blobs are in this colour 01762 01763 // Setup for rendering grid point rects... 01764 pRender->SetLineWidth(0); 01765 pRender->SetLineColour(COLOUR_TRANS); 01766 pRender->SetFillColour(GridColour); 01767 01768 DocRect ClipRect = pRender->GetClipRect(); // Get the current clip rect 01769 DocRect RendRect; 01770 01771 RendRect.lo.x = max(GridBoundingRect.lo.x,ClipRect.lo.x); // hi and lo renderable grid points 01772 RendRect.lo.y = max(GridBoundingRect.lo.y,ClipRect.lo.y); // derived from the clip rect and the 01773 RendRect.hi.x = min(GridBoundingRect.hi.x,ClipRect.hi.x); // node's bounding rect 01774 RendRect.hi.y = min(GridBoundingRect.hi.y,ClipRect.hi.y); 01775 01776 if (RendRect.IsValid()) 01777 { 01778 MILLIPOINT PixelWidth = pRender->GetScaledPixelWidth(); // the width of a single pixel 01779 01780 RenderPoints(pRender,RendRect,PixelWidth); // Render the grid points (crosshairs and sub grid dots) 01781 } 01782 01783 pRender->RestoreContext(); 01784 #endif 01785 } 01786 01787 /*********************************************************************************************** 01788 01789 > void NodeGridIso::RenderPoints(RenderRegion* pRender,DocRect RendRect,MILLIPOINT PixelWidth) 01790 01791 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 01792 Created: 15/2/94 01793 01794 Inputs: pRender = region to render to 01795 RendRect = Rectangle defining the renderable portion of the grid 01796 PixelWidth = width of a pixel in millipoints 01797 Outputs: 01798 Returns: 01799 Purpose: Renders the grid points within the given renderable rectangle 01800 Errors: 01801 Scope: private 01802 01803 ***********************************************************************************************/ 01804 01805 void NodeGridIso::RenderPoints(RenderRegion* pRender,DocRect RendRect,MILLIPOINT PixelWidth) 01806 { 01807 #if !defined(EXCLUDE_FROM_RALPH) 01808 TRACEUSER( "MarkN", _T("\n------------------\nNodeGridIso::RenderPoints\n\n")); 01809 01810 // Set the fp render step value to be the underlying main grid step value 01811 double fp_MainRenderStep = MainStep; 01812 01813 // Calculate the step for rendering the grid in relation to the width of a pixel and the 01814 // multiples of the dominant unit 01815 CalcGridRenderSteps(PixelWidth,&fp_MainRenderStep,fp_MainRenderStep*::GetUnitMultiple(Units),Units); 01816 01817 // Snap the render rect to these adjusted steps so we render all points within the renderable 01818 // portion of the grid 01819 01820 Snap(&RendRect.lo,fp_MainRenderStep); 01821 Snap(&RendRect.hi,fp_MainRenderStep); 01822 BOOL YOffAdjust = FALSE; // YOffAdjust = FALSE because we have snapped exactly to the main grid 01823 01824 if (RendRect.lo.x > RendRect.hi.x) Swap(RendRect.lo.x,RendRect.hi.x); 01825 if (RendRect.lo.y > RendRect.hi.y) Swap(RendRect.lo.y,RendRect.hi.y); 01826 01827 ENSURE(RendRect.IsValid(),"RendRect is invalid in NodeGridIso::RenderPoints"); 01828 01829 // Set the fp sub render step value to be the underlying sub grid step value 01830 double fp_SubRenderStep = SubStep; 01831 CalcGridRenderSteps(PixelWidth,&fp_SubRenderStep,fp_MainRenderStep,Units); 01832 if (fp_SubRenderStep >= fp_MainRenderStep) fp_SubRenderStep = 0; 01833 01834 // Get fixed point versions of the fp values for speedy grid rendering 01835 MILLIPOINT MainRenderStep = (MILLIPOINT)((fp_MainRenderStep * GRID_REND_FACTOR)+0.5); 01836 MILLIPOINT SubRenderStep = (MILLIPOINT)((fp_SubRenderStep * GRID_REND_FACTOR)+0.5); 01837 01838 // Convert RendRect to fixed point values 01839 RendRect.lo.x *= GRID_REND_FACTOR; 01840 RendRect.lo.y *= GRID_REND_FACTOR; 01841 RendRect.hi.x *= GRID_REND_FACTOR; 01842 RendRect.hi.y *= GRID_REND_FACTOR; 01843 01844 DocRect ScaledBB = GridBoundingRect; 01845 ScaledBB.lo.x *= GRID_REND_FACTOR; 01846 ScaledBB.lo.y *= GRID_REND_FACTOR; 01847 ScaledBB.hi.x *= GRID_REND_FACTOR; 01848 ScaledBB.hi.y *= GRID_REND_FACTOR; 01849 01850 RendRect.Inflate(MainRenderStep); YOffAdjust = !YOffAdjust; 01851 01852 // Make sure the render rectangle region doesn't lie outside the bounding rect 01853 while (RendRect.lo.x < ScaledBB.lo.x) { RendRect.lo.x += MainRenderStep; YOffAdjust = !YOffAdjust; } 01854 while (RendRect.lo.y < ScaledBB.lo.y) RendRect.lo.y += MainRenderStep; 01855 while (RendRect.hi.x > ScaledBB.hi.x) RendRect.hi.x -= MainRenderStep; 01856 while (RendRect.hi.y > ScaledBB.hi.y) RendRect.hi.y -= MainRenderStep; 01857 01858 RendRect.lo.x -= MainRenderStep; YOffAdjust = !YOffAdjust; // Need to plot to left of BB for sub grid dots 01859 RendRect.lo.y -= MainRenderStep; // Need to plot underneath BB for sub grid dots 01860 01861 RendRect.hi.x += GRID_REND_FACTOR; // compensate for errors (i.e. add the bodge factor) 01862 RendRect.hi.y += GRID_REND_FACTOR; // compensate for errors 01863 01864 RendRect.hi.y += MainRenderStep; 01865 01866 // Render those grid points boy! 01867 01868 DocCoord GridPoint,TrueGridPoint; 01869 MILLIPOINT yoff; 01870 01871 const MILLIPOINT Pix = pRender->GetScaledPixelWidth(); 01872 // const MILLIPOINT PixBy2 = Pix/2; 01873 const MILLIPOINT Length = PIX_CROSSHAIR_SIZE * Pix; 01874 01875 for (GridPoint.x=RendRect.lo.x;GridPoint.x<=RendRect.hi.x;GridPoint.x+=MainRenderStep) 01876 { 01877 if (YOffAdjust) yoff = MainRenderStep/2; else yoff = 0; 01878 01879 RendRect.lo.y += yoff; 01880 RendRect.hi.y += yoff; 01881 01882 for (GridPoint.y=RendRect.lo.y;GridPoint.y<=RendRect.hi.y;GridPoint.y+=MainRenderStep) 01883 { 01884 if (ScaledBB.ContainsCoord(GridPoint)) 01885 { 01886 // Scale the fixed point grid coord down to get the true coord of the grid point 01887 TrueGridPoint.x = (GridPoint.x+(GRID_REND_FACTOR/2)) / GRID_REND_FACTOR; 01888 TrueGridPoint.y = (GridPoint.y+(GRID_REND_FACTOR/2)) / GRID_REND_FACTOR; 01889 01890 // pRender->DrawCross(TrueGridPoint,PIX_CROSSHAIR_SIZE); 01891 // Phil says: Don't use DrawPixel because it can't be trusted to plot the 01892 // same pixel under GDI as it does under GDraw! 01893 // Instead draw two rectangles centered around the required coord. 01894 DocRect Horz(TrueGridPoint.x-Length, TrueGridPoint.y,TrueGridPoint.x+Length+Pix,TrueGridPoint.y+Pix); 01895 pRender->DrawRect(&Horz); 01896 01897 DocRect Vert(TrueGridPoint.x, TrueGridPoint.y-Length,TrueGridPoint.x+Pix,TrueGridPoint.y+Length+Pix); 01898 pRender->DrawRect(&Vert); 01899 } 01900 01901 if (SubRenderStep != 0) 01902 RenderSubPoints(pRender,GridPoint,MainRenderStep,SubRenderStep,PixelWidth,ScaledBB); 01903 } 01904 01905 RendRect.lo.y -= yoff; 01906 RendRect.hi.y -= yoff; 01907 01908 YOffAdjust = !YOffAdjust; 01909 } 01910 #endif 01911 } 01912 01913 01914 /*********************************************************************************************** 01915 01916 > void NodeGridIso::RenderSubPoints(RenderRegion* pRender, 01917 const DocCoord& MainGridPoint, 01918 MILLIPOINT MainRenderStep, 01919 MILLIPOINT SubRenderStep, 01920 MILLIPOINT PixelWidth, 01921 DocRect& ScaledBB) 01922 01923 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 01924 Created: 15/2/94 01925 01926 Inputs: pRender = region to render to 01927 MainGridPoint = coord of a main grid cross hair point (Scaled up by GRID_REND_FACTOR) 01928 MainRenderStep = step for rendering the main grid points (Scaled up by GRID_REND_FACTOR) 01929 SubRenderStep = step for rendering the sub grid points (Scaled up by GRID_REND_FACTOR) 01930 PixelWidth = width of a single pixel 01931 ScaledBB = The bounding rect of grid scaled up by GRID_REND_FACTOR 01932 Outputs: 01933 Returns: 01934 Purpose: Renders the sub grid points from the given main point 01935 Errors: 01936 Scope: private 01937 01938 ***********************************************************************************************/ 01939 01940 void NodeGridIso::RenderSubPoints( RenderRegion* pRender, 01941 const DocCoord& MainGridPoint, 01942 MILLIPOINT MainRenderStep, 01943 MILLIPOINT SubRenderStep, 01944 MILLIPOINT /*PixelWidth*/, 01945 DocRect& ScaledBB) 01946 { 01947 #if !defined(EXCLUDE_FROM_RALPH) 01948 DocCoord SubGridPoint,TrueSubGridPoint; 01949 MILLIPOINT maxx,maxy; 01950 01951 // Render the vertical sub grid dots from this point to the one above 01952 SubGridPoint.x = MainGridPoint.x; 01953 SubGridPoint.y = MainGridPoint.y+SubRenderStep; 01954 maxy = MainGridPoint.y+MainRenderStep; 01955 01956 const MILLIPOINT Pix = pRender->GetScaledPixelWidth(); 01957 // const MILLIPOINT PixBy2 = Pix/2; 01958 01959 while (SubGridPoint.y < maxy) 01960 { 01961 if (ScaledBB.ContainsCoord(SubGridPoint)) 01962 { 01963 // Scale the fixed point grid coord down to get the true coord of the grid point 01964 TrueSubGridPoint.x = (SubGridPoint.x+(GRID_REND_FACTOR/2)) / GRID_REND_FACTOR; 01965 TrueSubGridPoint.y = (SubGridPoint.y+(GRID_REND_FACTOR/2)) / GRID_REND_FACTOR; 01966 // pRender->DrawPixel(TrueSubGridPoint); 01967 // Phil says: Don't use DrawPixel because it can't be trusted to plot the 01968 // same pixel under GDI as it does under GDraw! 01969 // Instead draw a rectangle 1*1 pixels around the required coord. 01970 DocRect Pixel( TrueSubGridPoint.x, 01971 TrueSubGridPoint.y, 01972 TrueSubGridPoint.x+Pix, 01973 TrueSubGridPoint.y+Pix); 01974 pRender->DrawRect(&Pixel); 01975 } 01976 SubGridPoint.y += SubRenderStep; 01977 } 01978 01979 // Render the diagonal dots from this point to the one to the right and up 01980 SubGridPoint.x = MainGridPoint.x+SubRenderStep; 01981 SubGridPoint.y = MainGridPoint.y+(SubRenderStep/2); 01982 maxx = MainGridPoint.x+MainRenderStep; 01983 01984 while (SubGridPoint.x < maxx) 01985 { 01986 if (ScaledBB.ContainsCoord(SubGridPoint)) 01987 { 01988 // Scale the fixed point grid coord down to get the true coord of the grid point 01989 TrueSubGridPoint.x = (SubGridPoint.x+(GRID_REND_FACTOR/2)) / GRID_REND_FACTOR; 01990 TrueSubGridPoint.y = (SubGridPoint.y+(GRID_REND_FACTOR/2)) / GRID_REND_FACTOR; 01991 01992 // pRender->DrawPixel(TrueSubGridPoint); 01993 // Phil says: Don't use DrawPixel because it can't be trusted to plot the 01994 // same pixel under GDI as it does under GDraw! 01995 // Instead draw a rectangle 1*1 pixels around the required coord. 01996 DocRect Pixel( TrueSubGridPoint.x, 01997 TrueSubGridPoint.y, 01998 TrueSubGridPoint.x+Pix, 01999 TrueSubGridPoint.y+Pix); 02000 pRender->DrawRect(&Pixel); 02001 } 02002 SubGridPoint.x += SubRenderStep; 02003 SubGridPoint.y += SubRenderStep/2; 02004 } 02005 02006 // Render the diagonal dots from this point to the one to the right and down 02007 SubGridPoint.x = MainGridPoint.x+SubRenderStep; 02008 SubGridPoint.y = MainGridPoint.y-(SubRenderStep/2); 02009 maxx = MainGridPoint.x+MainRenderStep; 02010 02011 while (SubGridPoint.x < maxx) 02012 { 02013 if (ScaledBB.ContainsCoord(SubGridPoint)) 02014 { 02015 // Scale the fixed point grid coord down to get the true coord of the grid point 02016 TrueSubGridPoint.x = (SubGridPoint.x+(GRID_REND_FACTOR/2)) / GRID_REND_FACTOR; 02017 TrueSubGridPoint.y = (SubGridPoint.y+(GRID_REND_FACTOR/2)) / GRID_REND_FACTOR; 02018 02019 // pRender->DrawPixel(TrueSubGridPoint); 02020 // Phil says: Don't use DrawPixel because it can't be trusted to plot the 02021 // same pixel under GDI as it does under GDraw! 02022 // Instead draw a rectangle 1*1 pixels around the required coord. 02023 DocRect Pixel( TrueSubGridPoint.x, 02024 TrueSubGridPoint.y, 02025 TrueSubGridPoint.x+Pix, 02026 TrueSubGridPoint.y+Pix); 02027 pRender->DrawRect(&Pixel); 02028 } 02029 SubGridPoint.x += SubRenderStep; 02030 SubGridPoint.y -= SubRenderStep/2; 02031 } 02032 #endif 02033 } 02034 02035 02036 /*********************************************************************************************** 02037 02038 > BOOL NodeGridIso::Snap(DocCoord* pDocCoord) 02039 02040 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 02041 Created: 15/2/94 02042 Inputs: pDocCoord = a coord in Spread coords 02043 Outputs: 02044 Returns: TRUE - the DocCoord has been snapped to the grid. 02045 FALSE - the DocCoord has not been processed. 02046 02047 Purpose: Snaps to given coord to the nearest grid point. If it is not appropriate to snap 02048 the coord to the grid (at the moment this means the coord lies outside the grid object's 02049 bounding box), then FALSE is returned. 02050 Errors: 02051 Scope: public 02052 02053 **********************************************************************************************/ 02054 02055 BOOL NodeGridIso::Snap(DocCoord* pDocCoord) 02056 { 02057 if (IsDisabled()) return FALSE; 02058 02059 ENSURE(MainStep!=0,"MainStep==0 in NodeGridIso::Snap"); 02060 ENSURE(SubStep !=0,"SubStep ==0 in NodeGridIso::Snap"); 02061 02062 if (!GridBoundingRect.ContainsCoord(DocCoord(pDocCoord->x,pDocCoord->y))) 02063 return (FALSE); 02064 02065 MILLIPOINT x = SnapOrdinate(pDocCoord->x,SubStep,XOrigin); 02066 MILLIPOINT y = SnapOrdinate(pDocCoord->y,SubStep,CalcYOrigin(pDocCoord->x,SubStep)); 02067 02068 if (!GridBoundingRect.ContainsCoord(DocCoord(x,y))) 02069 return (FALSE); 02070 02071 pDocCoord->x = x; 02072 pDocCoord->y = y; 02073 02074 return (TRUE); 02075 } 02076 02077 /*********************************************************************************************** 02078 02079 > BOOL NodeGridIso::Snap(DocRect* pDocRect,const DocCoord& PrevCoord,const DocCoord& CurCoord) 02080 02081 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 02082 Created: 15/2/94 02083 Inputs: pDocCoord - the rectangle to snap 02084 StartDrag - Start coord of drag 02085 EndDrag - End coord of drag 02086 Outputs: 02087 Returns: TRUE - the DocRect been snapped to the grid. 02088 FALSE - the DocRect has not been processed. 02089 02090 Purpose: Snaps the given rect to the nearest position on the grid, preserving its width 02091 and height. 02092 The coords of the rect used for the snapping are determined by the PrevCoord and 02093 CurCoord coords supplied. This is done to allow the user to control how a 02094 selection rectangle is snapped to the grid by the direction of his/her last mouse 02095 movement. 02096 To force the bottom left hand corner of the rect to be snapped, 02097 supply PrevCoord=(0,0) and CurCoord(-1,-1). 02098 Scope: public 02099 02100 **********************************************************************************************/ 02101 02102 BOOL NodeGridIso::Snap(DocRect* pDocRect,const DocCoord& PrevCoord,const DocCoord& CurCoord) 02103 { 02104 if (IsDisabled()) return FALSE; 02105 02106 ENSURE(MainStep!=0,"MainStep==0 in NodeGridIso::Snap"); 02107 ENSURE(SubStep !=0,"SubStep ==0 in NodeGridIso::Snap"); 02108 02109 INT32 xdir = CurCoord.x - PrevCoord.x; 02110 INT32 ydir = CurCoord.y - PrevCoord.y; 02111 INT32 x,y,prevx, prevy; 02112 02113 if (LastXDir == 0) LastXDir = xdir; 02114 if (xdir == 0) xdir = LastXDir; 02115 LastXDir = xdir; 02116 02117 if (xdir <= 0) x = pDocRect->lo.x; else x = pDocRect->hi.x; 02118 02119 if (LastYDir == 0) LastYDir = ydir; 02120 if (ydir == 0) ydir = LastYDir; 02121 LastYDir = ydir; 02122 02123 if (ydir <= 0) y = pDocRect->lo.y; else y = pDocRect->hi.y; 02124 02125 if (!GridBoundingRect.ContainsCoord(DocCoord(x,y))) 02126 return (FALSE); 02127 02128 prevx = x; 02129 prevy = y; 02130 x = SnapOrdinate(x,SubStep,XOrigin); 02131 y = SnapOrdinate(y,SubStep,CalcYOrigin(x,SubStep)); 02132 02133 if (!GridBoundingRect.ContainsCoord(DocCoord(x,y))) 02134 return (FALSE); 02135 02136 pDocRect->Translate(x-prevx,y-prevy); 02137 02138 return (TRUE); 02139 } 02140 02141 /*********************************************************************************************** 02142 02143 > BOOL NodeGridIso::Snap(DocCoord* pDocCoord,MILLIPOINT Step) 02144 02145 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 02146 Created: 9/2/94 02147 Inputs: pDocCoord - the coord to snap 02148 XStep - the step to use when snapping the point 02149 Outputs: 02150 Returns: TRUE - the DocCoord has been snapped to the grid. 02151 FALSE - the DocCoord has not been processed. 02152 02153 Purpose: Same as Snap(pDocCoord), except the coord is snapped to grid points at the given intervals 02154 Errors: 02155 Scope: public 02156 02157 **********************************************************************************************/ 02158 02159 BOOL NodeGridIso::Snap(DocCoord* pDocCoord,double Step) 02160 { 02161 if (IsDisabled()) return FALSE; 02162 02163 ENSURE(Step!=0,"Step==0 in NodeGridIso::Snap"); 02164 02165 pDocCoord->x = SnapOrdinate(pDocCoord->x,Step,XOrigin); 02166 pDocCoord->y = SnapOrdinate(pDocCoord->y,Step,CalcYOrigin(pDocCoord->x,Step)); 02167 02168 return (TRUE); 02169 } 02170 02171 02172 /*********************************************************************************************** 02173 02174 > MILLIPOINT NodeGridIso::CalcYOrigin(MILLIPOINT x,double Step) 02175 02176 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 02177 Created: 16/2/94 02178 Inputs: x = Snapped x coord 02179 Step = step rate of underlying grid 02180 Outputs: 02181 Returns: The Y origin that should be used to snap Y coords to the grid 02182 Purpose: The Y origin used for snapping Y coords alternates between YOrigin and YOrigin+(Step/2) 02183 depending on a point's snapped x coord. This function returns the correct one to use. 02184 Errors: 02185 Scope: private 02186 02187 **********************************************************************************************/ 02188 02189 MILLIPOINT NodeGridIso::CalcYOrigin(MILLIPOINT x,double Step) 02190 { 02191 double xdist = mod((double)(x-XOrigin),Step*2); 02192 if (xdist<0) xdist = 0-xdist; 02193 02194 if ((xdist > (Step/2)) && (xdist < ((Step*2)-(Step/2))) ) 02195 return YOrigin+((MILLIPOINT)((Step/2)+0.5)); 02196 else 02197 return YOrigin; 02198 02199 02200 /* 02201 MILLIPOINT xdist = abs((x-XOrigin) % (Step*2)); 02202 02203 if ((xdist > (Step/2)) && (xdist < ((Step*2)-(Step/2))) ) 02204 return YOrigin+(Step/2); 02205 else 02206 return YOrigin; 02207 */ 02208 } 02209 02210 /*********************************************************************************************** 02211 02212 > Node* NodeGridIso::SimpleCopy() // Private method 02213 02214 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 02215 Created: 15/2/94 02216 02217 Inputs: - 02218 Outputs: 02219 Returns: A copy of the node, or NULL if memory runs out 02220 02221 Purpose: This method returns a shallow copy of the node with all Node pointers NULL. 02222 The function is virtual, and must be defined for all derived classes. 02223 02224 Errors: If memory runs out when trying to copy, then ERROR is called with an out of memory 02225 error and the function returns NULL. 02226 02227 02228 Scope: public 02229 **********************************************************************************************/ 02230 02231 Node* NodeGridIso::SimpleCopy() 02232 { 02233 NodeGridIso* NodeCopy = new NodeGridIso(); 02234 if (NodeCopy != NULL) 02235 CopyNodeContents(NodeCopy); 02236 return (NodeCopy); 02237 } 02238 02239 /*********************************************************************************************** 02240 > void NodeGridIso::CopyNodeContents(NodeGridIso* NodeCopy) 02241 02242 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 02243 Created: 15/2/94 02244 02245 Inputs: - 02246 Outputs: A copy of this node 02247 02248 Returns: - 02249 02250 Purpose: This method copies the node's contents to the node pointed to by NodeCopy. 02251 02252 Errors: An assertion failure will occur if NodeCopy is NULL 02253 02254 Scope: protected 02255 02256 ***********************************************************************************************/ 02257 02258 02259 void NodeGridIso::CopyNodeContents(NodeGridIso* NodeCopy) 02260 { 02261 ENSURE(NodeCopy != NULL,"Trying to copy a NodeGridIso's contents to a NULL node"); 02262 NodeGrid::CopyNodeContents(NodeCopy); 02263 02264 NodeCopy->MainStep = this->MainStep; 02265 NodeCopy->SubStep = this->SubStep; 02266 02267 NodeCopy->Units = this->Units; 02268 NodeCopy->Divisions = this->Divisions; 02269 NodeCopy->Subdivisions = this->Subdivisions; 02270 } 02271 02272 02273 /*********************************************************************************************** 02274 > void NodeGridIso::PolyCopyNodeContents(NodeRenderable* pNodeCopy) 02275 02276 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 02277 Created: 18/12/2003 02278 Outputs: - 02279 Purpose: Polymorphically copies the contents of this node to another 02280 Errors: An assertion failure will occur if NodeCopy is NULL 02281 Scope: protected 02282 02283 ***********************************************************************************************/ 02284 02285 void NodeGridIso::PolyCopyNodeContents(NodeRenderable* pNodeCopy) 02286 { 02287 ENSURE(pNodeCopy, "Trying to copy a node's contents into a NULL node"); 02288 ENSURE(IS_A(pNodeCopy, NodeGridIso), "PolyCopyNodeContents given wrong dest node type"); 02289 02290 if (IS_A(pNodeCopy, NodeGridIso)) 02291 CopyNodeContents((NodeGridIso*)pNodeCopy); 02292 } 02293 02294 02295 02296 /******************************************************************************************** 02297 02298 > void* NodeGridIso::GetDebugDetails(StringBase* Str) 02299 02300 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 02301 Created: 15/2/94 02302 Inputs: - 02303 Outputs: Str: String giving debug info about the node 02304 Returns: - 02305 Purpose: For obtaining debug information about the Node 02306 Errors: - 02307 SeeAlso: - 02308 02309 ********************************************************************************************/ 02310 02311 02312 void NodeGridIso::GetDebugDetails(StringBase* Str) 02313 { 02314 NodeGrid::GetDebugDetails(Str); 02315 } 02316 02317 02318 //-------------------------------------------------------------------------------------------- 02319 02320 #ifdef _DEBUG 02321 02322 void NodeGridIso::ShowDebugTreeDetails() const 02323 { 02324 TRACE( _T("NodeGridIso::ShowDebugTreeDetails() ")); 02325 Node::ShowDebugTreeDetails(); 02326 } 02327 02328 #endif 02329 02330 //-------------------------------------------------------------------------------------------- 02331 02332 /******************************************************************************************** 02333 > BOOL NodeGridIso::SetGridParams(double Div,UINT32 Subdiv,UnitType NewUnits, BOOL Scale=TRUE) 02334 02335 Author: Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com> 02336 Created: 16/10/95 02337 Inputs: Div - Number of Units between each main step of the grid 02338 Subdiv - Number of subdivisions between each main grid point 02339 NewUnits - The units the grid is defined in 02340 Scale - account for unit scaling (only FALSE when loading for compatibility with old docs) 02341 Returns: FALSE if fails 02342 Purpose: Defines the grid. 02343 ********************************************************************************************/ 02344 02345 BOOL NodeGridIso::SetGridParams(double Div,UINT32 Subdiv,UnitType NewUnits, BOOL Scale) 02346 { 02347 if (Div < 0) 02348 { 02349 ERROR3("NodeGridIso::SetGridParams() - Div < 0!"); 02350 Div = 0.0; 02351 } 02352 if (Subdiv < 1) 02353 { 02354 ERROR3("NodeGridIso::SetGridParams() - SubDiv < 1!"); 02355 Subdiv = 1; 02356 } 02357 02358 DimScale* pDimScale = DimScale::GetPtrDimScale(this); 02359 ERROR2IF(pDimScale==NULL,FALSE,"NodeGridRect::SetGridParams() - pDimScale==NULL"); 02360 02361 // set the raw values in the grid - but only set units if scaling turned off 02362 // (except if scaling is not to be accounted for - ie during loading for compatibility with old docs - yuk!) 02363 Divisions = Div; 02364 Subdivisions = Subdiv; 02365 if (Scale==FALSE || pDimScale->GetScaleUnits()==NOTYPE) 02366 Units = NewUnits; 02367 02368 // convert the divisions and units into a millipoint grid spacing (accounting for unit scaling) - yuk! 02369 double GridSpacing=0; 02370 if (Scale) 02371 { 02372 BOOL ok = pDimScale->ComponentsToMillipoint(&GridSpacing, Divisions, GetUnits()); 02373 if (!ok) return FALSE; 02374 } 02375 else 02376 { 02377 DocUnitList* pDocUnitList = DocUnitList::GetCurrentDocUnitList(); 02378 ERROR2IF(pDocUnitList==NULL,FALSE,"DimScale::ComponentsToMillipoint() - pDocUnitList==NULL"); 02379 Unit* pUnit = pDocUnitList->FindUnit(Units); 02380 ERROR2IF(pUnit==NULL,FALSE,"DimScale::ComponentsToMillipoint() - pUnit==NULL"); 02381 GridSpacing = Div * pUnit->GetMillipoints(); 02382 } 02383 02384 if (GridSpacing<1) 02385 { 02386 ERROR3("NodeGridIso::SetGridParams() - GridSpacing < 1!"); 02387 GridSpacing=1; 02388 } 02389 02390 MainStep = GridSpacing; 02391 SubStep = MainStep/Subdivisions; 02392 if (SubStep<1) 02393 { 02394 ERROR3("NodeGridIso::SetGridParams() - SubXStep < 1!"); 02395 SubStep=1; 02396 } 02397 02398 return TRUE; 02399 } 02400 02401 02402 /******************************************************************************************** 02403 > double NodeGridIso::GetDivisions(BOOL Scale=TRUE) 02404 02405 Author: Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com> 02406 Created: 17/10/95 02407 Inputs: Scale - account for scaling (only FALSE when saving for doc compatibility) 02408 Returns: Number of Units between each main grid point 02409 Purpose: Used to get the number of Units between each main grid point. 02410 ********************************************************************************************/ 02411 02412 double NodeGridIso::GetDivisions(BOOL Scale) 02413 { 02414 return NodeGrid::CalcDivisions(Scale); 02415 } 02416 02417 02418 /******************************************************************************************** 02419 02420 > UINT32 NodeGridIso::GetSubdivisions() 02421 02422 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 02423 Created: 1/3/94 02424 Inputs: - 02425 Outputs: - 02426 Returns: Num subdivisions 02427 Purpose: Used to get the number of subdivisions between each main grid point. 02428 Errors: - 02429 SeeAlso: - 02430 02431 ********************************************************************************************/ 02432 02433 UINT32 NodeGridIso::GetSubdivisions() 02434 { 02435 return Subdivisions; 02436 } 02437 02438 /******************************************************************************************** 02439 > UnitType NodeGridIso::GetUnits(BOOL Scale=TRUE) 02440 02441 Author: Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com> 02442 Created: 20/10/95 02443 Inputs: Scale - account for unit scaling (only FALSE when saving for compatibility with old docs) 02444 Returns: Units used by the grid 02445 Purpose: Gets the units used by the grid 02446 ********************************************************************************************/ 02447 02448 UnitType NodeGridIso::GetUnits(BOOL Scale) 02449 { 02450 DimScale* pDimScale = DimScale::GetPtrDimScale(this); 02451 ERROR2IF(pDimScale==NULL,NOTYPE,"NodeGridIso::GetUnits() - pDimScale==NULL"); 02452 02453 // if scaling turned on return scale units 02454 // (except if scaling is not to be accounted for - ie during saving for compatibility with old docs) 02455 UnitType ScaleUnits = pDimScale->GetScaleUnits(); 02456 if (Scale && ScaleUnits!=NOTYPE) 02457 return ScaleUnits; 02458 02459 return Units; 02460 } 02461 02462 02463 //--------------------------------------------- 02464 //--------------------------------------------- 02465 02466 /******************************************************************************************** 02467 02468 > static void NodeGrid::ProcessAllGrids(ProcessGrid* pProcessGrid) 02469 02470 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 02471 Created: 18/7/94 02472 Inputs: pProcessGrid = ptr to the object that will process each grid in the current doc 02473 Returns: - 02474 Purpose: Processes all the grids in the current doc using the grid processing object 02475 provided as a parameter 02476 SeeAlso: - 02477 02478 ********************************************************************************************/ 02479 02480 void NodeGrid::ProcessAllGrids(ProcessGrid* pProcessGrid) 02481 { 02482 ERROR3IF(Document::GetSelected() == NULL,"What, no doc? Surely some mistake!"); 02483 02484 pProcessGrid->pDoc = Document::GetSelected(); 02485 if (pProcessGrid->pDoc == NULL) return; 02486 02487 // Now we need to scan all spreads throughout the current doc 02488 02489 pProcessGrid->pChapter = Node::FindFirstChapter(pProcessGrid->pDoc); 02490 while (pProcessGrid->pChapter != NULL) 02491 { 02492 // For each chapter in the doc... 02493 Node* pNode = pProcessGrid->pChapter->FindFirstChild(); 02494 while (pNode != NULL) 02495 { 02496 // If the child node of the chapter is a spread... 02497 if (pNode->IsKindOf(CC_RUNTIME_CLASS(Spread))) 02498 ProcessGridsInSpread(pProcessGrid,(Spread*)pNode); 02499 02500 pNode = pNode->FindNext(); 02501 } 02502 pProcessGrid->pChapter = pProcessGrid->pChapter->FindNextChapter(); 02503 } 02504 } 02505 02506 02507 /******************************************************************************************** 02508 02509 > static void NodeGrid::ProcessGridsInSpread(ProcessGrid* pProcessGrid,Spread* pSpread) 02510 02511 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 02512 Created: 18/7/94 02513 Inputs: pProcessGrid = ptr to the object that will process each grid in the current doc 02514 pSpread = spread containing grids to be processed 02515 Returns: - 02516 Purpose: Processes all grids in this spread using the given grid processor param 02517 SeeAlso: - 02518 02519 ********************************************************************************************/ 02520 02521 void NodeGrid::ProcessGridsInSpread(ProcessGrid* pProcessGrid,Spread* pSpread) 02522 { 02523 pProcessGrid->pSpread = pSpread; 02524 02525 // scan the children of the spread for grids 02526 Node* pNode = pSpread->FindFirstChild(); 02527 while (pNode != NULL) 02528 { 02529 if (pNode->IsKindOf(CC_RUNTIME_CLASS(NodeGrid))) 02530 // we now have a ptr to a grid, so process it 02531 pProcessGrid->Process((NodeGrid*)pNode); 02532 02533 pNode = pNode->FindNext(); 02534 } 02535 } 02536 02537 //------- 02538 //------- 02539 //------- 02540 02541 /******************************************************************************************** 02542 02543 > void ProcessGridForceRedraw::Process(NodeGrid* pGrid) 02544 02545 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 02546 Created: 18/7/94 02547 Inputs: pGrid = the grid to force a redraw on 02548 Returns: - 02549 Purpose: Forces a redraw on the given grid 02550 SeeAlso: - 02551 02552 ********************************************************************************************/ 02553 02554 void ProcessGridForceRedraw::Process(NodeGrid* pGrid) 02555 { 02556 if (!pGrid->IsDisabled()) 02557 { 02558 // Get ptr to selected doc view 02559 DocView* pDocView = DocView::GetSelected(); 02560 02561 // If there's a selected docview, redraw! 02562 if (pDocView != NULL) 02563 pDocView->ForceRedraw(pSpread,pGrid->GetBlobBoundingRect()); 02564 } 02565 } 02566 02567 //-------- 02568 //-------- 02569 //-------- 02570 02571 /******************************************************************************************** 02572 02573 > ProcessGridUnitMsg::ProcessGridUnitMsg(UnitMsg* pThisUnitMsg) 02574 02575 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 02576 Created: 18/7/94 02577 Inputs: pUnitMsg = ptr to the unit msg 02578 Returns: - 02579 Purpose: THE constructor for this class 02580 This assigns pThisUnitMsg to the member var pUnitMsg ready for its 02581 Process method to be called vai NodeGrid::ProcessAllGrids() 02582 SeeAlso: - 02583 02584 ********************************************************************************************/ 02585 02586 ProcessGridUnitMsg::ProcessGridUnitMsg(UnitMsg* pThisUnitMsg) 02587 { 02588 pUnitMsg = pThisUnitMsg; 02589 } 02590 02591 /******************************************************************************************** 02592 02593 > void ProcessGridUnitMsg::Process(NodeGrid* pGrid) 02594 02595 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 02596 Created: 18/7/94 02597 Inputs: pGrid = the grid to process 02598 Returns: - 02599 Purpose: Checks to see if the grid is using the unit specified in the UnitMsg 02600 member var, and if so changes it if the unit is about to be deleted 02601 SeeAlso: - 02602 02603 ********************************************************************************************/ 02604 02605 void ProcessGridUnitMsg::Process(NodeGrid* pGrid) 02606 { 02607 switch (pUnitMsg->MsgType) 02608 { 02609 case (UnitMsg::BEFOREDELETE) : 02610 { 02611 UnitType OldUnitType = pUnitMsg->ThisUnitType; 02612 02613 if (pGrid->GetUnits() == OldUnitType) 02614 { 02615 double Div = pGrid->GetDivisions(); 02616 UINT32 SubDiv = pGrid->GetSubdivisions(); 02617 Unit* pThisUnit = pUnitMsg->pDocUnitList->FindUnit(OldUnitType); 02618 UnitType NewUnitType = pThisUnit->GetBaseUnitType(); 02619 02620 ENSURE(NewUnitType != NOTYPE,"Er, deleting a unit that has no base type"); 02621 02622 Div = Convert::ConvertToNewUnits(Div,OldUnitType,NewUnitType); 02623 02624 pGrid->SetGridParams(Div,SubDiv,NewUnitType); 02625 } 02626 } 02627 break; 02628 02629 case (UnitMsg::CHANGED) : 02630 { 02631 UnitType ChangedUnitType = pUnitMsg->ThisUnitType; 02632 02633 if (pGrid->GetUnits() == ChangedUnitType) 02634 { 02635 double Div = pGrid->GetDivisions(); 02636 UINT32 SubDiv = pGrid->GetSubdivisions(); 02637 02638 pGrid->SetGridParams(Div,SubDiv,ChangedUnitType); 02639 02640 if (!pGrid->IsDisabled()) 02641 { 02642 // Get ptr to selected doc view 02643 DocView* pDocView = DocView::GetSelected(); 02644 02645 // If there's a selected docview, redraw! 02646 if (pDocView != NULL) 02647 pDocView->ForceRedraw(pGrid->FindParentSpread(),pGrid->GetBlobBoundingRect()); 02648 } 02649 02650 //GridTool::ForceRedraw(pGrid); 02651 } 02652 } 02653 break; 02654 default: break; 02655 } 02656 } 02657 02658 /******************************************************************************************** 02659 02660 > static void NodeGrid::ForceRedrawAllGrids() 02661 02662 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 02663 Created: 19/10/94 02664 Inputs: - 02665 Returns: - 02666 Purpose: Forces a redraw on all the grids in the current view 02667 SeeAlso: 02668 02669 ********************************************************************************************/ 02670 02671 void NodeGrid::ForceRedrawAllGrids() 02672 { 02673 ProcessGridForceRedraw ProcGrid; 02674 NodeGrid::ProcessAllGrids(&ProcGrid); 02675 } 02676 02677 /******************************************************************************************** 02678 > static void NodeGrid::MakeDefaultGrid(Spread* pSpread, BOOL Scale=TRUE) 02679 02680 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 02681 Created: 12/5/94 02682 Inputs: pSpread = spread in which to make the Default grid 02683 Scale - account for unit scaling (only FALSE when loading for doc compatibility) 02684 Purpose: Creates a grid covering the whole spread. The grid is 02685 defined using the default parameters. 02686 ********************************************************************************************/ 02687 02688 void NodeGrid::MakeDefaultGrid(Spread* pSpread, BOOL Scale) 02689 { 02690 if (pSpread != NULL) 02691 { 02692 NodeGrid* pNewGrid = NULL; // This will point to the new grid 02693 switch (GetDefaultGridType()) // Create the new grid of the right type 02694 { 02695 case RECTANGULAR : pNewGrid = new NodeGridRect(); break; 02696 case ISOMETRIC : pNewGrid = new NodeGridIso(); break; 02697 default: break; // we check it below 02698 } 02699 02700 if (pNewGrid != NULL) 02701 { 02702 // Build the grid rectangle to completely cover the pasteboard 02703 DocRect Rect = pSpread->GetPasteboardRect(FALSE); 02704 pSpread->DocCoordToSpreadCoord(&Rect); 02705 02706 pNewGrid->AttachNode(pSpread, LASTCHILD); 02707 // pNewGrid->SetInitialBounds(Rect); 02708 pNewGrid->SetBoundingRect(Rect); // Tell the NodeGrid of the new bounds 02709 pNewGrid->SetDefault(TRUE); 02710 pNewGrid->SetDisabled(GetDefaultGridDisabled()); 02711 02712 // Set the grid (and user coord) origin to the bottom left corner of the 1st page 02713 // DocRect PageRect; 02714 // if (pSpread->GetPagesRect(&PageRect)) 02715 // pNewGrid->SetOrigin(PageRect.lo.x, PageRect.lo.y); 02716 02717 // Set the grid params to the default grid settings 02718 // If the default unit type is NOTYPE, get the page units from the doc unit list 02719 // of the current document 02720 UnitType Units = GetDefaultUnits(); 02721 if (Units == NOTYPE) 02722 { 02723 // Get the node's dic unit list 02724 DocUnitList* pDocUnitList = DocUnitList::GetCurrentDocUnitList(); 02725 02726 ENSURE(pDocUnitList != NULL,"No doc unit list attached to this doc yet"); 02727 if (pDocUnitList != NULL) 02728 Units = pDocUnitList->GetPageUnits(); // Set to the page units. 02729 } 02730 02731 if (Units != NOTYPE) 02732 pNewGrid->SetGridParams(GetDefaultDivisions(),GetDefaultSubdivisions(),Units,Scale); 02733 } 02734 } 02735 } 02736 02737 /******************************************************************************************** 02738 02739 > static void NodeGrid::ResetDocRectSnap() 02740 02741 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 02742 Created: 20/10/94 02743 Inputs: - 02744 Outputs: - 02745 Returns: - 02746 Purpose: Call this before starting a drag that will use the DocRect version of the snap function 02747 SeeAlso: - 02748 02749 ********************************************************************************************/ 02750 02751 void NodeGrid::ResetDocRectSnap() 02752 { 02753 LastXDir = LastYDir = 0; 02754 } 02755 02756 //---------------------------------------------- 02757 // Moved these from the class def in grid.h so that they are no longer in-line, 02758 // hence allowing them to be called from DLLs 02759 02760 UINT32 NodeGrid::GetNumSelectedGrids() { return NumSelected; } 02761 UINT32 NodeGrid::GetNumNonDefaultSelectedGrids() { return NumNonDefaultSelected; } 02762 02763 GridType NodeGrid::GetTypeForDefaultGrid() { return TypeForDefaultGrid; } 02764 BOOL NodeGrid::GetDefaultGridDisabled() { return DefaultGridDisabled; } 02765 double NodeGrid::GetDefaultDivisions() { return DefaultDivisions; } 02766 UINT32 NodeGrid::GetDefaultSubdivisions() { return DefaultSubdivisions; } 02767 UnitType NodeGrid::GetDefaultUnits() { return DefaultUnits; } 02768 GridType NodeGrid::GetDefaultGridType() { return DefaultGridType; } 02769 02770 void NodeGrid::SetTypeForDefaultGrid(GridType GType) { TypeForDefaultGrid = GType; } 02771 void NodeGrid::SetDefaultGridDisabled(BOOL state) { DefaultGridDisabled = state; } 02772 void NodeGrid::SetDefaultDivisions(double Div) { DefaultDivisions = Div; } 02773 void NodeGrid::SetDefaultSubdivisions(UINT32 Sub) { DefaultSubdivisions = Sub; } 02774 void NodeGrid::SetDefaultUnits(UnitType UType) { DefaultUnits = UType; } 02775 void NodeGrid::SetDefaultGridType(GridType GType) { DefaultGridType = GType; } 02776 02777 //-------------------------------------------------------------------- 02778 //-------------------------------------------------------------------- 02779 // Support functions for unit processing 02780 //-------------------------------------------------------------------- 02781 //-------------------------------------------------------------------- 02782 02783 static UnitType GetDominantUnit(UnitType ThisUnit) 02784 { 02785 // for (INT32 u=0;(u<NUM_DEFAULT_UNIT_TYPES) && (UnitDataList[u].Units != Units);u++) ; 02786 // if (u >= NUM_DEFAULT_UNIT_TYPES) return NOTYPE; else return UnitDataList[u].DominantUnit; 02787 02788 DocUnitList* pDocUnitList = DocUnitList::GetCurrentDocUnitList(); 02789 Unit* pThisUnit = pDocUnitList->FindUnit(ThisUnit); 02790 double NumMills = pThisUnit->GetMillipoints(); 02791 02792 UnitType ThisUnitBaseType = pThisUnit->GetBaseUnitType(); 02793 if (ThisUnitBaseType != NOTYPE) 02794 { 02795 Unit* pBaseUnit = pDocUnitList->FindUnit(pThisUnit->GetBaseUnitType()); 02796 02797 if (NumMills < pBaseUnit->GetMillipoints()) 02798 return (pBaseUnit->GetUnitType()); 02799 } 02800 02801 INT32 NumUnits = pDocUnitList->GetNumUnits(); 02802 INT32 u; 02803 double ResultMills = 1.7E308; 02804 UnitType ResultUnitType = NOTYPE; 02805 02806 for (u=0;u < NumUnits;u++) 02807 { 02808 Unit* pUnit = pDocUnitList->FindUnit(u); 02809 UnitType BaseUnitType = pUnit->GetBaseUnitType(); 02810 02811 if (BaseUnitType != NOTYPE) 02812 { 02813 if (BaseUnitType == ThisUnit) 02814 { 02815 double m = pUnit->GetMillipoints(); 02816 if ((m > NumMills) && (m < ResultMills)) 02817 { 02818 ResultMills = m; 02819 ResultUnitType = pUnit->GetUnitType(); 02820 } 02821 } 02822 } 02823 } 02824 02825 return ResultUnitType; 02826 } 02827 02828 static double GetUnitMultiple(UnitType Units) 02829 { 02830 // for (INT32 u=0;(u<NUM_DEFAULT_UNIT_TYPES) && (UnitDataList[u].Units != Units);u++) ; 02831 // if (u >= NUM_DEFAULT_UNIT_TYPES) return 1; else return UnitDataList[u].Multiple; 02832 02833 UnitType DomUnitType = ::GetDominantUnit(Units); 02834 02835 if (DomUnitType == NOTYPE) 02836 return 2.0; 02837 02838 DocUnitList* pDocUnitList = DocUnitList::GetCurrentDocUnitList(); 02839 Unit* pUnit = pDocUnitList->FindUnit(Units); 02840 Unit* pDomUnit = pDocUnitList->FindUnit(DomUnitType); 02841 double Multiple; 02842 02843 if (pUnit->GetBaseUnitType() == pDomUnit->GetUnitType()) 02844 Multiple = pUnit->GetBaseDenominator() / pUnit->GetBaseNumerator(); 02845 else 02846 Multiple = pDomUnit->GetBaseNumerator() / pDomUnit->GetBaseDenominator(); 02847 02848 if (Multiple <= 1.0) 02849 return 2.0; 02850 else 02851 return Multiple; 02852 } 02853 02854 /* 02855 static struct 02856 { 02857 UnitType Units; 02858 TCHAR* Suffix; 02859 UINT32 Multiple; 02860 UnitType DominantUnit; 02861 } UnitDataList[NUM_DEFAULT_UNIT_TYPES] = 02862 { 02863 { MILLIMETRES, "mm", 10, CENTIMETRES }, 02864 { CENTIMETRES, "cm", 100, METRES }, 02865 { METRES, "m" , 1000, NOTYPE }, 02866 { INCHES, "in", 12, FEET }, 02867 { FEET, "ft", 3, YARDS }, 02868 { YARDS, "yd", 1760, NOTYPE }, 02869 { COMP_POINTS, "pt", 72, PICAS }, 02870 { PICAS, "pi", 6, INCHES }, 02871 { MILLIPOINTS, "mp", 1000, COMP_POINTS } 02872 }; 02873 */ 02874 02875 02876 //static TCHAR* GetUnitSuffix(UnitType Units) 02877 //{ 02878 // for (INT32 u=0;(u<NUM_DEFAULT_UNIT_TYPES) && (UnitDataList[u].Units != Units);u++) ; 02879 // if (u >= NUM_DEFAULT_UNIT_TYPES) return ""; else return UnitDataList[u].Suffix; 02880 02881 // Unit* pUnit = pDocUnitList->FindUnit(DomUnitType); 02882 // String_32 Spec = pUnit->GetSpecifier(); 02883 // return ((TCHAR*)Spec); 02884 //} 02885 02886 //------------- 02887 //--------------------------------------------------------------- 02888 //--------------------------------------------------------------- 02889 //--------------------------------------------------------------- 02890 02891 /******************************************************************************************** 02892 02893 > virtual BOOL NodeGrid::WritePreChildrenWeb(BaseCamelotFilter* pFilter) 02894 02895 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 02896 Created: 6/8/96 02897 Inputs: pFilter = ptr to the filter 02898 Returns: TRUE if record is written, FALSE if not 02899 Purpose: Writes the grid record to the filter (if it's required) 02900 SeeAlso: Node::WritePreChildrenWeb(BaseCamelotFilter* pFilter) 02901 02902 ********************************************************************************************/ 02903 02904 BOOL NodeGrid::WritePreChildrenWeb(BaseCamelotFilter* pFilter) 02905 { 02906 // do nothing in the web format 02907 return FALSE; 02908 } 02909 02910 //-------------------------------------------------------------- 02911 // See NodeGrid::WritePreChildrenWeb(BaseCamelotFilter* pFilter) 02912 // 02913 BOOL NodeGrid::WritePreChildrenNative(BaseCamelotFilter* pFilter) 02914 { 02915 #ifdef DO_EXPORT 02916 BOOL RecordWritten = TRUE; 02917 02918 // Write out the page sizes etc for this spread 02919 if (RecordWritten) RecordWritten = WriteGridAndRulerSettings(pFilter); 02920 if (RecordWritten) RecordWritten = WriteGirdAndRulerOrigin(pFilter); 02921 02922 return RecordWritten; 02923 #else 02924 return TRUE; 02925 #endif //DO_EXPORT 02926 } 02927 02928 /******************************************************************************************** 02929 02930 > BOOL NodeGrid::WriteGridAndRulerSettings(BaseCamelotFilter* pFilter) 02931 02932 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 02933 Created: 6/8/96 02934 Input: pFilter = ptr to the filter to export to 02935 Outputs: - 02936 Returns: TRUE if ok, FALSE otherwise 02937 Purpose: Exports the settings for the grid and rulers to the filter. 02938 This is the default grid, as this acts as the settings for the grid, 02939 as you would expect, and the page rulers. 02940 SeeAlso: NodeGrid::WritePreChildrenNative; NodeGrid::WritePreChildrenWeb; 02941 02942 ********************************************************************************************/ 02943 02944 BOOL NodeGrid::WriteGridAndRulerSettings(BaseCamelotFilter* pFilter) 02945 { 02946 #ifdef DO_EXPORT 02947 ERROR2IF(pFilter == NULL,FALSE,"NULL filter param"); 02948 02949 BOOL ok = FALSE; 02950 02951 // Only write out this set of details if it is the default grid 02952 if (IsDefault()) 02953 { 02954 // Go and get the numbers out of the grid 02955 // BODGE - old builds (hence docs) save the grid spacing in divisions and units but don't 02956 // account for unit scaling, so as not to change doc format new docs do the same so we must 02957 // read the grid 'Divisions' with scaling turned off - yuk! 02958 // But surely, it is safer to save out the units unscaled! 02959 BOOL Scale = FALSE; 02960 double Divisions = GetDivisions(Scale); 02961 UnitType Unit = GetUnits(Scale); 02962 UINT32 SubDivisions = GetSubdivisions(); 02963 GridType TypeOfGrid = GetGridType(); 02964 02965 // Convert the unittype into a reference 02966 UnitListComponent * pUnitsComponent = pFilter->GetUnitDocComponent(); 02967 ERROR2IF(pUnitsComponent == NULL,FALSE,"WriteGridAndRulerSettings No units doc component present"); 02968 02969 INT32 UnitsRef = pUnitsComponent->GetWriteUnitReference(Unit, pFilter); 02970 02971 CXaraFileRecord Rec(TAG_GRIDRULERSETTINGS, TAG_GRIDRULERSETTINGS_SIZE); 02972 02973 ok = Rec.Init(); 02974 02975 if (ok) ok = Rec.WriteINT32(UnitsRef); 02976 if (ok) ok = Rec.WriteDOUBLE(Divisions); 02977 if (ok) ok = Rec.WriteUINT32(SubDivisions); 02978 if (ok) ok = Rec.WriteBYTE((BYTE)TypeOfGrid); 02979 02980 // Finally, write the record out to file 02981 // In the process get the record number that this was written out as 02982 INT32 RecordNumber = 0L; 02983 if (ok) RecordNumber = pFilter->Write(&Rec); 02984 02985 // If we have had a problem at any of the stages then return that to the caller 02986 if (!ok || RecordNumber <= 0) 02987 ok = FALSE; 02988 } 02989 02990 return ok; 02991 #else 02992 return TRUE; 02993 #endif //DO_EXPORT 02994 } 02995 02996 /******************************************************************************************** 02997 02998 > BOOL Spread::WriteGirdAndRulerOrigin(BaseCamelotFilter* pFilter) 02999 03000 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 03001 Created: 6/8/96 03002 Input: pFilter = ptr to the filter to export to 03003 Outputs: - 03004 Returns: TRUE if ok, FALSE otherwise 03005 Purpose: Exports the origin for the grid and ruler to the filter. 03006 This is the default grid, as this acts as the settings for the grid, 03007 as you would expect, and the page rulers. 03008 SeeAlso: NodeGrid::WritePreChildrenNative; NodeGrid::WritePreChildrenWeb; 03009 03010 ********************************************************************************************/ 03011 03012 BOOL NodeGrid::WriteGirdAndRulerOrigin(BaseCamelotFilter* pFilter) 03013 { 03014 #ifdef DO_EXPORT 03015 ERROR2IF(pFilter == NULL,FALSE,"NULL filter param"); 03016 03017 BOOL ok = FALSE; 03018 03019 // Only write out this set of details if it is the default grid 03020 if (IsDefault()) 03021 { 03022 // Read the grid (user) origin 03023 DocCoord Origin(0,0); 03024 GetOrigin(&Origin.x, &Origin.y); 03025 03026 // We will now translate this to be relative to the page origin, as it will be displayed 03027 // to the user 03028 Spread* pSpread = pFilter->GetSpread(); 03029 DocCoord PageRelGridOrigin = Origin; 03030 if (pSpread) 03031 pSpread->SpreadCoordToPagesCoord(&PageRelGridOrigin, Origin); 03032 03033 CXaraFileRecord Rec(TAG_GRIDRULERORIGIN, TAG_GRIDRULERORIGIN_SIZE); 03034 03035 ok = Rec.Init(); 03036 03037 // Write out the origin 03038 if (ok) ok = Rec.WriteCoord(PageRelGridOrigin); 03039 03040 // Finally, write the record out to file 03041 // In the process get the record number that this was written out as 03042 INT32 RecordNumber = 0L; 03043 if (ok) RecordNumber = pFilter->Write(&Rec); 03044 03045 // If we have had a problem at any of the stages then return that to the caller 03046 if (!ok || RecordNumber <= 0) 03047 ok = FALSE; 03048 } 03049 03050 03051 return ok; 03052 #else 03053 return TRUE; 03054 #endif //DO_EXPORT 03055 } 03056