backgrnd.cpp

Go to the documentation of this file.
00001 // $Id: backgrnd.cpp 1664 2006-08-04 10:06:16Z gerry $
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 // OpBackground implementation
00099 
00100 /*
00101 */
00102 
00103 #include "camtypes.h"
00104 
00105 #include "backgrnd.h"   // OpBackground
00106 
00107 //#include "document.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00108 //#include "spread.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00109 #include "page.h"
00110 #include "layer.h"
00111 #include "sprdmsg.h"    // SpreadMsg
00112 #include "nodershp.h"   // NodeRegularShape
00113 #include "lineattr.h"   // AttrStrokeColourChange
00114 //#include "attrmgr.h"  // AttributeManager - in camtypes.h [AUTOMATICALLY REMOVED]
00115 #include "qualattr.h"   // QualityAttribute
00116 
00117 //#include "galstr.h"       // _R(IDS_BACKGROUNDLAYERNAME)
00118 
00119 CC_IMPLEMENT_DYNCREATE(OpBackground, UndoableOperation)
00120 CC_IMPLEMENT_MEMDUMP(OpBackgroundParam, OpParam)
00121 
00122 #define new CAM_DEBUG_NEW
00123 
00124 //--------------------------------------------------------------------------------------------
00125 //--------------------------------------------------------------------------------------------
00126 //--------------------------------------------------------------------------------------------
00127 
00128 #if !defined(EXCLUDE_FROM_RALPH)
00129 
00130 /***********************************************************************************************
00131 
00132 >   OpBackground::OpBackground()
00133 
00134     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00135     Created:    26/3/97
00136     Inputs:     -
00137     Outputs:    -
00138     Returns:    -
00139     Purpose:    Default constructor
00140     SeeAlso:    UndoableOperation
00141         
00142 ***********************************************************************************************/
00143 
00144 OpBackground::OpBackground()
00145 {
00146 //  m_pDoc = NULL;
00147 //  m_pSpread = NULL;
00148 //  m_pDocColour = NULL;
00149 //  m_pBitmap = NULL;
00150 
00151     // Versions of the parameters used in the drag and drop process
00152 //  m_pDroppedBitmap = NULL;
00153 //  m_pDroppedDocColour = NULL;
00154 }
00155 
00156 
00157 /***********************************************************************************************
00158 
00159 >   OpBackground::~OpBackground()
00160 
00161     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00162     Created:    26/3/97
00163     Inputs:     -
00164     Outputs:    -
00165     Returns:    -
00166     Purpose:    Default destructor
00167     SeeAlso:    UndoableOperation
00168         
00169 ***********************************************************************************************/
00170 
00171 OpBackground::~OpBackground()
00172 {
00173 }
00174 
00175 /***********************************************************************************************
00176 
00177 >   void OpBackground::DoWithParam(OpDescriptor* pOpDesc,OpParam* pParam)
00178 
00179     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00180     Created:    26/3/97
00181     Inputs:     pOpDesc = ptr op desc
00182                 pOpParam = param block to use
00183     Outputs:    -
00184     Returns:    -
00185     Purpose:    This function is used to create a guideline in the selected spread.
00186                 It calls DoAddNewGuideline() with pParam->Param1 specifying the guideline type.
00187     SeeAlso:    DoAddNewGuideline(), OilRuler::OnLButtonDown()
00188         
00189 ***********************************************************************************************/
00190 
00191 void OpBackground::DoWithParam(OpDescriptor* pOpDesc,OpParam* pParam)
00192 {
00193     ERROR3IF(pParam == NULL,"pParam is NULL");
00194 
00195     TRACEUSER("Gerry", _T("OpBackground::DoWithParam"));
00196 
00197     if (pParam != NULL)
00198     {
00199         BOOL ok = TRUE;
00200 
00201         OpBackgroundParam* pOpBackgroundParam = (OpBackgroundParam*)pParam;
00202 //      Document *      pDoc        = pOpBackgroundParam->pDoc;
00203         Spread *        pSpread     = pOpBackgroundParam->pSpread;
00204         DocColour *     pDocColour  = pOpBackgroundParam->pDocColour;
00205         KernelBitmap *  pBitmap     = pOpBackgroundParam->pBitmap;
00206 
00207         // If no spread is given then use the selected one
00208         if (pSpread == NULL)
00209         {
00210             // We will work off the currently selected spread
00211             pSpread = Document::GetSelectedSpread();
00212         }
00213 
00214         // Go and do the job of making the page background
00215         ok = DoMakePageBackground(this, pSpread, pBitmap, pDocColour);
00216     }
00217 
00218     End();
00219 }
00220 
00221 /***********************************************************************************************
00222 
00223 >   static BOOL OpBackground::MakePageBackground(UndoableOperation * pOp, Spread * pSpread, DocColour * pDocColour)
00224 
00225     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00226     Created:    7/4/97
00227     Inputs:     pOp         - the operation to use
00228                 pSpread     - the spread to apply the background to
00229                 pDocColour  - the doc colour to apply
00230     Outputs:    -
00231     Returns:    True if worked ok, False otherwise.
00232     Purpose:    Tries to apply the DocColour or bitmap as a new page background.
00233                 
00234                 It is up to the caller to call End() on the operation. This is so
00235                 that an outside op should be able to call this and everything should
00236                 work ok.
00237     SeeAlso:    -
00238         
00239 ***********************************************************************************************/
00240 
00241 BOOL OpBackground::MakePageBackground(UndoableOperation * pOp, Spread * pSpread, DocColour * pDocColour)
00242 {
00243     ERROR2IF(pOp == NULL || pSpread == NULL || pDocColour == NULL,FALSE,"MakePageBackground Bad params!");
00244 
00245     // Get the op to do its stuff
00246     BOOL ok = DoMakePageBackground(pOp, pSpread, NULL, pDocColour);
00247 
00248     return ok;
00249 }
00250 
00251 /***********************************************************************************************
00252 
00253 >   static BOOL OpBackground::MakePageBackground(UndoableOperation * pOp, Spread * pSpread, KernelBitmap * pBitmap)
00254 
00255     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00256     Created:    7/4/97
00257     Inputs:     pOp         - the operation to use
00258                 pSpread     - the spread to apply the background to
00259                 pBitmap     - the bitmap to apply
00260     Outputs:    -
00261     Returns:    True if worked ok, False otherwise.
00262     Purpose:    Tries to apply the DocColour or bitmap as a new page background.
00263                 
00264                 It is up to the caller to call End() on the operation. This is so
00265                 that an outside op should be able to call this and everything should
00266                 work ok.
00267     SeeAlso:    -
00268         
00269 ***********************************************************************************************/
00270 
00271 BOOL OpBackground::MakePageBackground(UndoableOperation * pOp, Spread * pSpread, KernelBitmap * pBitmap)
00272 {
00273     ERROR2IF(pOp == NULL || pSpread == NULL || pBitmap == NULL,FALSE,"MakePageBackground Bad params!");
00274 
00275     // Get the op to do its stuff
00276     BOOL ok = DoMakePageBackground(pOp, pSpread, pBitmap);
00277 
00278     return ok;
00279 }
00280 
00281 /***********************************************************************************************
00282 
00283 >   static BOOL OpBackground::DoMakePageBackground(UndoableOperation * pOp, Spread * pSpread, KernelBitmap * pBitmap,
00284                                                    DocColour * pDocColour = NULL)
00285 
00286     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00287     Created:    7/4/97
00288     Inputs:     pOp         - the operation to use
00289                 pSpread     - the spread to apply the background to
00290                 pBitmap     - the bitmap to apply
00291                 pDocColour  - the doc colour to apply
00292     Outputs:    -
00293     Returns:    True if worked ok, False otherwise.
00294     Purpose:    Tries to apply the DocColour or bitmap as a new page background.
00295                 
00296                 It is up to the caller to call End() on the operation. This is so
00297                 that an outside op should be able to call this and everything should
00298                 work ok.
00299     SeeAlso:    -
00300         
00301 ***********************************************************************************************/
00302 
00303 BOOL OpBackground::DoMakePageBackground(UndoableOperation * pOp, Spread * pSpread, KernelBitmap * pBitmap,
00304                                         DocColour * pDocColour)
00305 {
00306     TRACEUSER("Gerry", _T("OpBackground::DoMakePageBackground"));
00307 
00308     // Our inputs are actually set up in the class variables, so check them
00309     ERROR2IF(pSpread == NULL || pOp == NULL,FALSE,"DoMakePageBackground Bad params!");
00310     ERROR2IF(pDocColour == NULL && pBitmap == NULL,FALSE,"DoMakePageBackground Bad params!");
00311 
00312     BOOL    ok      = TRUE;
00313     Page    *pPage  = pSpread->FindFirstPageInSpread ();
00314     DocRect Bounds  = pPage->GetPageRect ();
00315 
00316     // If there's a transparent background colour, just hide the existing node.
00317     if ( pDocColour != NULL && pDocColour->IsTransparent () )
00318     {
00319         Layer*  pOldLayer   = pSpread->FindFirstPageBackgroundLayer ();
00320 
00321         // Attempt to remove the old background layer.
00322         if ( pOldLayer != NULL )
00323         {
00324             TRACEUSER("Gerry", _T("Removing old background"));
00325             if ( !pOp->DoHideNode(pOldLayer, TRUE ) )
00326             {
00327                 // Something went wrong, so handle the error.
00328                 ERROR3( "OpBackground failed to hide the old page background" );
00329                 pOp->FailAndExecute ();
00330                 ok = FALSE;
00331             }
00332         }
00333     }
00334 
00335     // Otherwise create a new background layer.
00336     else
00337     {
00338         TRACEUSER("Gerry", _T("Creating new background"));
00339         Layer* pBackgroundLayer = DoCreateBackgroundLayer(pOp, pSpread);
00340 
00341         if (pBackgroundLayer == NULL)
00342         {
00343             ERROR3("Something went wrong with the layer creation");
00344             pOp->FailAndExecute();
00345             ok = FALSE;
00346         }
00347         else
00348         {
00349             // Try and find an existing page filling rectangle on this layer
00350             NodeRegularShape * pShape = DoFindPageRectangle(pSpread, pBackgroundLayer);
00351 
00352             // If not found then create a new one
00353             if (pShape != NULL)
00354             {
00355                 // Hide the old version of the rectangle
00356                 if (!pOp->DoHideNode(pShape, TRUE))
00357                 {
00358                     ERROR3("OpBackground failed to hide the old node");
00359                     pOp->FailAndExecute();
00360                     ok = FALSE;
00361                 }
00362             }
00363 
00364             if (ok)
00365             {
00366                 // Make a new rectangle of the correct size
00367                 pShape = DoCreateRectangle(pSpread);
00368 
00369                 // Apply the bitmap or the colour to it before we insert it into the tree.
00370                 if (pDocColour)
00371                 {
00372                     // Set the colour to be the background.
00373                     ok = ApplyDocColour(pDocColour, pShape);
00374                 }
00375                 else if (pBitmap)
00376                 {
00377                     ok = ApplyBitmap(pBitmap, pShape);
00378                 }
00379                 else
00380                 {
00381                     ERROR3("OpBackground Haven't got anything to apply");
00382                     pOp->FailAndExecute();
00383                     ok = FALSE;
00384                 }
00385 
00386                 // Apply a useful set of default attibutes on top of the fill colour
00387                 // or bitmap fill.
00388                 if ( pShape != NULL )
00389                 {
00390                     ApplyDefaultAttributes(pShape);
00391                 }
00392             }
00393 
00394             // We must make the layer unlocked so that we don't get the stupid
00395             // inserting on locked layer message
00396             pBackgroundLayer->SetLocked(FALSE);
00397 
00398             // And now insert it into the background layer
00399             if (ok && !pOp->DoInsertNewNode(pShape, pBackgroundLayer, FIRSTCHILD,FALSE,
00400                                             FALSE,FALSE,FALSE))
00401             {
00402                 delete pShape;
00403                 pShape = NULL;
00404                 pOp->FailAndExecute();
00405                 ok = FALSE;
00406             }
00407 
00408             // Set the layer back to locked as we have finished inserting onto the layer
00409             pBackgroundLayer->SetLocked(TRUE);
00410 
00411             // Since we prevented DoInsertnewNode from invalidating, it won't have cleared
00412             // the cache appropriately so we will have to do that ourselves...
00413             if (ok)
00414                 pBackgroundLayer->ReleaseCached();
00415         }
00416     }
00417 
00418     // Force a redraw of the new background layer.
00419     if ( ok && !pOp->DoInvalidateRegion ( pSpread, Bounds ) )
00420     {
00421         pOp->FailAndExecute();
00422         ok = FALSE;
00423     }
00424 
00425     return ok;
00426 }
00427 
00428 /***********************************************************************************************
00429 
00430 >   static NodeRegularShape * OpBackground::DoFindPageRectangle(Spread * pSpread, Layer* pBackgroundLayer)
00431 
00432     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00433     Created:    27/3/97
00434     Inputs:     pSpread             - the spread to apply the background to
00435                 pBackgroundLayer    - the layer to search for the shape on
00436     Outputs:    -
00437     Returns:    The regular shape, if found
00438     Purpose:    Tries to find the page filling rectangle on the specified layer.
00439     SeeAlso:    -
00440         
00441 ***********************************************************************************************/
00442 
00443 NodeRegularShape * OpBackground::DoFindPageRectangle(Spread * pSpread, Layer* pBackgroundLayer)
00444 {
00445     if (pSpread == NULL || pBackgroundLayer == NULL)
00446         return NULL;
00447 
00448     // We want to find the rectangle which should be the same size as the current union of
00449     // all the pages on the current spread
00450     DocRect PagesRect;
00451     pSpread->GetPagesRect(&PagesRect);
00452 
00453     return FindPageRectangle(pBackgroundLayer, PagesRect);
00454 }
00455 
00456 /***********************************************************************************************
00457 
00458 >   static NodeRegularShape * OpBackground::FindPageRectangle(Layer* pBackgroundLayer, const DocRect& PagesRect)
00459 
00460     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00461     Created:    4/4/97
00462     Inputs:     The layer to search for the shape on
00463                 The encompassing rectangle of the current pages
00464     Outputs:    -
00465     Returns:    The regular shape, if found
00466     Purpose:    Tries to find the page filling rectangle on the specified layer.
00467     SeeAlso:    -
00468         
00469 ***********************************************************************************************/
00470 
00471 NodeRegularShape * OpBackground::FindPageRectangle(Layer* pBackgroundLayer, const DocRect& PagesRect)
00472 {
00473     ERROR2IF(pBackgroundLayer == NULL,FALSE,"OpBackground::FindPageRectangle Bad params error!");
00474 
00475     NodeRegularShape *pShape = NULL;
00476     NodeRegularShape *pRegNode = NULL;
00477     Node * pNode = pBackgroundLayer->FindFirstChild();
00478     DocRect rect;
00479     const MILLIPOINT delta = 1000;
00480     while (pNode != NULL)
00481     {
00482         // Only check regular shape nodes 
00483         if (pNode->IS_KIND_OF(NodeRegularShape))
00484         {
00485             // Only check rectangles
00486             pRegNode = (NodeRegularShape *)pNode;
00487             if (pRegNode->IsARectangle())
00488             {
00489                 //DocCoord MinorAxis NodeRegularShape::GetMinorAxes();
00490                 // The bounding rect should be roughly what we want
00491                 rect = pRegNode->GetBoundingRect(TRUE, FALSE);
00492                 if (
00493                     (PagesRect.lo.x > rect.lo.x - delta) && (PagesRect.lo.x < rect.lo.x + delta) &&
00494                     (PagesRect.hi.x > rect.hi.x - delta) && (PagesRect.hi.x < rect.hi.x + delta) &&
00495                     (PagesRect.lo.y > rect.lo.y - delta) && (PagesRect.lo.y < rect.lo.y + delta) &&
00496                     (PagesRect.hi.y > rect.hi.y - delta) && (PagesRect.hi.y < rect.hi.y + delta)
00497                    )
00498                 {
00499                     pShape = pRegNode;
00500                 }
00501             }
00502         }
00503 
00504         pNode = pNode->FindNext();
00505     }
00506 
00507     return pShape;
00508 }
00509 
00510 /***********************************************************************************************
00511 
00512 >   static NodeRegularShape * OpBackground::DoCreateRectangle(Spread * pSpread)
00513 
00514     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00515     Created:    27/3/97
00516     Inputs:     pSpread             - the spread to apply the background to
00517     Outputs:    -
00518     Returns:    The regular shape
00519     Purpose:    Returns a new rectangle the size of the current spread.
00520     SeeAlso:    -
00521         
00522 ***********************************************************************************************/
00523 
00524 NodeRegularShape * OpBackground::DoCreateRectangle(Spread * pSpread)
00525 {
00526     ERROR2IF(pSpread == NULL,FALSE,"OpBackground::DoCreateRectangle Bad params error!");
00527 
00528     if (pSpread == NULL)
00529         return NULL;
00530 
00531     // This assumes that we have already checked to see if there is a page covering rectangle
00532     // already present on this layer.
00533 
00534     // Create a new rectangle node on the layer
00535     NodeRegularShape *pShape = new NodeRegularShape;
00536     if (pShape != NULL)
00537     {
00538         BOOL ok = pShape->SetUpShape();
00539 
00540         if (!ok)
00541         {
00542             // Do something sensible in here
00543             delete pShape;
00544             return NULL;
00545         }
00546 
00547         // We want to make the rectangle the same size as the current union of
00548         // all the pages on the current spread
00549         DocRect Rect;
00550         pSpread->GetPagesRect(&Rect);
00551 
00552         /* // We must expand the rectangle by a single pixel as the page redraw
00553         // draws a single pixel line around the outside.
00554         const MILLIPOINT pixel = (MILLIPOINT)(72000.0/96.0);
00555         Rect.Inflate(pixel); */
00556 
00557         const INT32 CornerRadius = 0; // No curvature
00558         
00559         if (pShape->MakeRectangle(Rect.Width(), Rect.Height(), CornerRadius))
00560         {
00561             // Translate centre from 0,0 to required position relative to page
00562             INT32 XTrans = Rect.lo.x + (Rect.Width()/2);
00563             INT32 YTrans = Rect.lo.y + (Rect.Height()/2);
00564             Trans2DMatrix Trans(XTrans, YTrans);
00565 
00566             pShape->Transform(Trans);
00567 
00568             // finish off the shape
00569             pShape->InvalidateBoundingRect();
00570         }
00571     }
00572 
00573     return pShape;
00574 }
00575 
00576 /***********************************************************************************************
00577 
00578 >   static BOOL OpBackground::ApplyDocColour(DocColour * pColourToApply, NodeRegularShape * pShape)
00579 
00580     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00581     Created:    27/3/97
00582     Inputs:     The colour to apply
00583                 The regular shape to apply the colour to
00584     Outputs:    -
00585     Returns:    
00586     Purpose:    Applies the specified colour to the specified NodeRegularShape.
00587     SeeAlso:    -
00588         
00589 ***********************************************************************************************/
00590 
00591 BOOL OpBackground::ApplyDocColour(DocColour * pColourToApply, NodeRegularShape * pShape)
00592 {
00593     ERROR2IF(pColourToApply == NULL || pShape == NULL,FALSE,"OpBackground::ApplyDocColour Bar params!");
00594 
00595     // Set up a fill colour attribute
00596     AttrFlatColourFill *pFillColAttr = new AttrFlatColourFill();
00597     if (pFillColAttr == NULL)
00598     {
00599         InformError();
00600         return(FALSE);
00601     }
00602 
00603     ((AttrFillGeometry*)pFillColAttr)->SetStartColour(pColourToApply);
00604 
00605     // And now insert it as a child of the regular shape
00606     // Factoring should be ok as the Regular Shape is assumed to be the child of
00607     // layer
00608     pFillColAttr->AttachNode(pShape, FIRSTCHILD);
00609 
00610     return TRUE;
00611 }
00612 
00613 /***********************************************************************************************
00614 
00615 >   static BOOL OpBackground::ApplyBitmap(KernelBitmap * pBitmapToApply, NodeRegularShape * pShape)
00616 
00617     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00618     Created:    27/3/97
00619     Inputs:     The bitmap to apply
00620                 The regular shape to apply the bitmap to
00621     Outputs:    -
00622     Returns:    
00623     Purpose:    Applies the specified bitmap to the specified NodeRegularShape.
00624     SeeAlso:    -
00625         
00626 ***********************************************************************************************/
00627 
00628 BOOL OpBackground::ApplyBitmap(KernelBitmap * pBitmapToApply, NodeRegularShape * pShape)
00629 {
00630     ERROR2IF(pBitmapToApply == NULL || pShape == NULL,FALSE,"OpBackground::ApplyBitmap Bar params!");
00631 
00632     // Set up a fill colour attribute
00633     AttrBitmapColourFill *pBitmapFillAttr = new AttrBitmapColourFill();
00634     if (pBitmapFillAttr == NULL)
00635     {
00636         InformError();
00637         return(FALSE);
00638     }
00639 
00640     // Set the coordinates of the fill end points
00641     // We want to start the fill at the top left of the regular shape
00642     // The bounding rect should be roughly what we want
00643     DocRect Rect = pShape->GetBoundingRect(TRUE, FALSE);
00644                 
00645     // Get the size of the bitmap taking into account its DPI
00646     INT32 Width = pBitmapToApply->GetRecommendedWidth();
00647     INT32 Height = pBitmapToApply->GetRecommendedHeight();
00648     // You would think that the handles on the fill correspond to where you place them
00649     // but oh now the displayed handles are shown at different points. So instead of
00650     // positioning the start in the centre of the bitmap, you need to position it bottom left
00651     // The End should be centre and right but needs to be bottom right.
00652     // The End2 should be centre and top but needs to be top left.
00653 
00654     // We want the start point to be half the height of the bitmap below this
00655     //DocCoord Start(Rect.lo.x + Width/2, Rect.hi.y - Height/2);
00656     DocCoord Start(Rect.lo.x, Rect.hi.y - Height);
00657     // We want the other end point to be same height as the centre point
00658     // but on the far right of the rectangle i.e the full width across
00659     //DocCoord End(Rect.lo.x + Width, Rect.hi.y - Height/2);
00660     DocCoord End(Rect.lo.x + Width, Rect.hi.y - Height);
00661     // We want the end point to be middle and top of the rectangle
00662     //DocCoord End2(Rect.lo.x + Width/2, Rect.hi.y);
00663     DocCoord End2(Rect.lo.x, Rect.hi.y);
00664 
00665     ((AttrFillGeometry*)pBitmapFillAttr)->SetStartPoint(&Start);
00666     ((AttrFillGeometry*)pBitmapFillAttr)->SetEndPoint(&End);
00667     ((AttrFillGeometry*)pBitmapFillAttr)->SetEndPoint2(&End2);
00668 
00669     // Now attach the correct bitmap to the fill
00670     ((AttrFillGeometry*)pBitmapFillAttr)->AttachBitmap(pBitmapToApply);
00671 
00672     // And now insert it as a child of the regular shape
00673     // Factoring should be ok as the Regular Shape is assumed to be the child of
00674     // layer
00675     pBitmapFillAttr->AttachNode(pShape, FIRSTCHILD);
00676 
00677     return TRUE;
00678 }
00679 
00680 /***********************************************************************************************
00681 
00682 >   static BOOL OpBackground::ApplyDefaultAttributes(NodeRegularShape * pShape)
00683 
00684     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00685     Created:    1/4/97
00686     Inputs:     The regular shape to apply the attributes to
00687     Outputs:    -
00688     Returns:    
00689     Purpose:    Applies some useful default attributes to the specified NodeRegularShape.
00690     SeeAlso:    -
00691         
00692 ***********************************************************************************************/
00693 
00694 BOOL OpBackground::ApplyDefaultAttributes(NodeRegularShape * pShape)
00695 {
00696     ERROR2IF(pShape == NULL,FALSE,"OpBackground::ApplyDefaultAttributes Bar params!");
00697 
00698     // *****
00699     // Set up a no colour line colour
00700     AttrStrokeColour * pLineColAttr = new AttrStrokeColour();
00701     if (pLineColAttr == NULL)
00702     {
00703         InformError();
00704         return(FALSE);
00705     }
00706 
00707     DocColour ColNone(COLOUR_NONE);
00708     ((AttrFillGeometry*)pLineColAttr)->SetStartColour(&ColNone);
00709     // And now insert it as a child of the regular shape
00710     // Factoring should be ok as the Regular Shape is assumed to be the child of
00711     // layer
00712     pLineColAttr->AttachNode(pShape, LASTCHILD);
00713 
00714 
00715 
00716     // *****
00717     // Set up a line width attribute
00718     AttrLineWidth *pLineWidthAttr = new AttrLineWidth();
00719     if (pLineWidthAttr == NULL)
00720     {
00721         InformError();
00722         return(FALSE);
00723     }
00724 
00725     ((AttrLineWidth*)pLineWidthAttr)->Value.LineWidth = 0;
00726 
00727     // And now insert it as a child of the regular shape
00728     // Factoring should be ok as the Regular Shape is assumed to be the child of
00729     // layer
00730     pLineWidthAttr->AttachNode(pShape, LASTCHILD);
00731 
00732 
00733     // *****
00734     // Set up a join type attribute
00735     AttrJoinType  * pJoinTypeAttr = new AttrJoinType();
00736     if (pLineWidthAttr == NULL)
00737     {
00738         InformError();
00739         return(FALSE);
00740     }
00741 
00742     // We will use a default constructed one as this should be vaguely correct
00743     // ((AttrLineWidth*)pJoinTypeAttr)->Value.LineWidth = 0;
00744 
00745     // And now insert it as a child of the regular shape
00746     // Factoring should be ok as the Regular Shape is assumed to be the child of
00747     // layer
00748     pJoinTypeAttr->AttachNode(pShape, LASTCHILD);
00749 
00750     return TRUE;
00751 }
00752 
00753 
00754 /***********************************************************************************************
00755 
00756 >   static Layer* OpBackground::DoCreateBackgroundLayer(UndoableOperation * pOp, Spread * pSpread)
00757 
00758     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00759     Created:    26/3/97
00760     Inputs:     pOp                 - The operation to use
00761                 pSpread             - the spread to apply the background to
00762     Outputs:    -
00763     Returns:    Ptr to the background layer, or NULL one couldn't be created.
00764     Purpose:    This returns a ptr to the background layer.
00765 
00766                 If the background layer already exists, a ptr to it is returned.
00767 
00768                 If there isn't a background layer, it is created and inserted into the doc tree.
00769                 If this fails the func returns NULL
00770 
00771     SeeAlso:    OpBackground::DoNewGuideline()
00772         
00773 ***********************************************************************************************/
00774 
00775 Layer* OpBackground::DoCreateBackgroundLayer(UndoableOperation * pOp, Spread * pSpread)
00776 {
00777     ERROR2IF(pOp == NULL || pSpread == NULL,FALSE,"OpBackground::DoCreateBackgroundLayer Bad params error!");
00778 
00779     // Search for our special page background layer
00780     Layer* pFoundLayer = pSpread->FindFirstPageBackgroundLayer();
00781     // If we have found it then return this to the caller as we don't want
00782     // more than one present!
00783     if (pFoundLayer != NULL)
00784         return pFoundLayer;
00785 
00786     // We didn't find a page background layer so go and create a new one
00787     Layer* pNewLayer = CreateBackgroundLayer();
00788     if (pNewLayer != NULL)
00789     {
00790         // If we insert the new layer as the FIRSTCHILD then this will be like the guidelayer
00791         // and behind the page. If we insert as the last child then we will be at the front of
00792         // the stacking order. We need to insert ourselves as the node after the last page node
00793         Page *pLastPage = pSpread->FindLastPageInSpread();
00794 
00795         // Insert the new layer as the next node after the last page.
00796         if (pLastPage && pOp->DoInsertNewNode(pNewLayer, pLastPage, NEXT, FALSE,FALSE,FALSE,FALSE))
00797         {
00798             pNewLayer->EnsureUniqueLayerID();
00799             BROADCAST_TO_ALL(SpreadMsg(pSpread, SpreadMsg::LAYERCHANGES));
00800         }
00801         else
00802         {
00803             delete pNewLayer;
00804             pNewLayer = NULL;
00805         }
00806     }
00807 
00808     return pNewLayer;
00809 }
00810 
00811 
00812 
00813 /***********************************************************************************************
00814 
00815 >   static Layer* OpBackground::CreateBackgroundLayer()
00816 
00817     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00818     Created:    26/3/97
00819     Inputs:     -
00820     Outputs:    -
00821     Returns:    Ptr to a background layer that's ready to be inserted into the tree
00822     Purpose:    This does everything required in creating a layer fit to be called the background layer
00823     SeeAlso:    -
00824         
00825 ***********************************************************************************************/
00826 
00827 Layer* OpBackground::CreateBackgroundLayer()
00828 {
00829     Layer* pNewLayer = new Layer;
00830     if (pNewLayer != NULL)
00831     {
00832         String_256 LayerName(_R(IDS_BACKGROUNDLAYERNAME));
00833 
00834         pNewLayer->SetVisible(TRUE); 
00835         pNewLayer->SetLocked(TRUE); 
00836         pNewLayer->SetPrintable(FALSE); 
00837         pNewLayer->SetBackground(TRUE); 
00838         pNewLayer->SetOutline(FALSE);
00839         pNewLayer->SetGuide(FALSE);
00840         pNewLayer->SetPageBackground(TRUE);     // This is the special page background layer flag
00841         pNewLayer->SetLayerID(LayerName); 
00842 
00843 /*      // Ensure we are always rendered at maximum quality so that turning WYSIWYG
00844         // down does not remove the page background!
00845         Quality Qual;
00846         Qual.SetQuality(QUALITY_MAX);
00847         QualityAttribute QualAttr(Qual);
00848         NodeAttribute* pNodeAttr = QualAttr.MakeNode();
00849         pNodeAttr->AttachNode(pNewLayer, FIRSTCHILD); */
00850     }
00851 
00852     return pNewLayer;
00853 }
00854 
00855 /***********************************************************************************************
00856 
00857 >   static BOOL OpBackground::FixBackgroundLayer(Layer * pBackgroundLayer, const DocRect& NewPagesRect,
00858                                                  const DocRect& OldPagesRect)
00859 
00860     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00861     Created:    4/4/97
00862     Inputs:     The background layer to fix
00863                 The encompassing size of the new pages in the spread
00864                 The encompassing size of the old pages in the spread
00865     Outputs:    -
00866     Returns:    Ptr to a background layer that's ready to be inserted into the tree
00867     Purpose:    This tries to fix up the special page background layer so that the rectangle
00868                 on it is resized to the cover the newly resized pages on the spread.
00869     SeeAlso:    Spread::SetPageSize;
00870         
00871 ***********************************************************************************************/
00872 
00873 BOOL OpBackground::FixBackgroundLayer(Layer * pBackgroundLayer, const DocRect& NewPagesRect,
00874                                       const DocRect& OldPagesRect)
00875 {
00876     ERROR2IF(pBackgroundLayer == NULL,FALSE,"OpBackground::FixBackgroundLayer Bad params!");
00877     
00878     //BOOL ok = TRUE;
00879 
00880     // There should be a rectangle on the page encompassing the old position of the pages
00881     // so go and try and find it
00882     NodeRegularShape * pShape = FindPageRectangle(pBackgroundLayer, OldPagesRect);
00883     // If no rectangle is found then something might be slightly wrong. Should we error?
00884     if (pShape)
00885     {
00886         const INT32 CornerRadius = 0; // No curvature
00887         if (pShape->MakeRectangle(NewPagesRect.Width(), NewPagesRect.Height(), CornerRadius))
00888         {
00889             // Translate centre from 0,0 to required position relative to page
00890             INT32 XTrans = NewPagesRect.lo.x + (NewPagesRect.Width()/2);
00891             INT32 YTrans = NewPagesRect.lo.y + (NewPagesRect.Height()/2);
00892             Trans2DMatrix Trans(XTrans, YTrans);
00893 
00894             pShape->Transform(Trans);
00895 
00896             // finish off the shape
00897             pShape->InvalidateBoundingRect();
00898         }
00899     
00900         // Find any bitmap fills and fix up the fill origin etc.
00901         Node * pNode = pShape->FindFirstChild();
00902         while (pNode != NULL)
00903         {
00904             // Only check and fix bitmap colour fill attributes of the regular shape nodes 
00905             if (pNode->IS_KIND_OF(AttrBitmapColourFill))
00906             {
00907                 // Convert the pointer to the correct type
00908                 AttrBitmapColourFill * pBitmapFillAttr = (AttrBitmapColourFill*)pNode;
00909 
00910                 // Set the coordinates of the fill end points
00911                 // We want to start the fill at the top left of the regular shape
00912                 // The bounding rect should be roughly what we want
00913                 DocRect Rect = pShape->GetBoundingRect(TRUE, FALSE);
00914                             
00915                 KernelBitmap * pBitmap = ((AttrFillGeometry*)pBitmapFillAttr)->GetBitmap();             
00916                 // Get the size of the bitmap taking into account its DPI
00917                 INT32 Width = pBitmap->GetRecommendedWidth();
00918                 INT32 Height = pBitmap->GetRecommendedHeight();
00919                 // You would think that the handles on the fill correspond to where you place them
00920                 // but oh now the displayed handles are shown at different points. So instead of
00921                 // positioning the start in the centre of the bitmap, you need to position it bottom left
00922                 // The End should be centre and right but needs to be bottom right.
00923                 // The End2 should be centre and top but needs to be top left.
00924 
00925                 // We want the start point to be half the height of the bitmap below this
00926                 //DocCoord Start(Rect.lo.x + Width/2, Rect.hi.y - Height/2);
00927                 DocCoord Start(Rect.lo.x, Rect.hi.y - Height);
00928                 // We want the other end point to be same height as the centre point
00929                 // but on the far right of the rectangle i.e the full width across
00930                 //DocCoord End(Rect.lo.x + Width, Rect.hi.y - Height/2);
00931                 DocCoord End(Rect.lo.x + Width, Rect.hi.y - Height);
00932                 // We want the end point to be middle and top of the rectangle
00933                 //DocCoord End2(Rect.lo.x + Width/2, Rect.hi.y);
00934                 DocCoord End2(Rect.lo.x, Rect.hi.y);
00935 
00936                 ((AttrFillGeometry*)pBitmapFillAttr)->SetStartPoint(&Start);
00937                 ((AttrFillGeometry*)pBitmapFillAttr)->SetEndPoint(&End);
00938                 ((AttrFillGeometry*)pBitmapFillAttr)->SetEndPoint2(&End2);
00939             }
00940         
00941             pNode = pNode->FindNext();
00942         }       
00943     }
00944 
00945     return TRUE;
00946 }
00947 
00948 
00949 /***********************************************************************************************
00950 
00951 >   static BOOL OpBackground::GetPageColour(Spread *pSpread, KernelBitmap **ppOutBitmap, 
00952                                                                 DocColour **ppOutColour)
00953 
00954     Author:     Stefan_Stoykov (Xara Group Ltd) <camelotdev@xara.com>
00955     Created:    23/6/97
00956     Inputs:     pSpread - a spread
00957     Outputs:    ppOutBitmap - receives the page bitmap, if a bitmap colour fill is applied to it
00958                 ppOutColour - receives the page colour, if a flat colour fill is applied to it
00959     Returns:    TRUE, if succesful, FALSE otherwise
00960     Purpose:    Gets the page's fill attribute, which could only be either a colour, or a bitmap
00961         
00962 ***********************************************************************************************/
00963 
00964 BOOL OpBackground::GetPageColour(Spread *pSpread, KernelBitmap **ppOutBitmap, 
00965                                                         DocColour **ppOutColour)
00966 {
00967     ERROR2IF(pSpread == NULL,FALSE,"OpBackground::GetPageColour Bad params error!");
00968     ERROR2IF(ppOutBitmap == NULL || ppOutColour == NULL,FALSE,"OpBackground::GetPageColour Bad params error!");
00969 
00970     // Search for our special page background layer
00971     Layer* pFoundLayer = pSpread->FindFirstPageBackgroundLayer();
00972     if (pFoundLayer == NULL)
00973         return FALSE;
00974 
00975     // search for our page node
00976     NodeRegularShape *pNode = DoFindPageRectangle(pSpread, pFoundLayer);
00977 
00978     if (!pNode)
00979         return FALSE;
00980 
00981     // find the fill attribute applied to the page
00982     NodeAttribute *pAppliedAttr = NULL;
00983     pNode->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrFillGeometry),&pAppliedAttr);
00984 
00985     if (pAppliedAttr != NULL)
00986     {
00987         if (IS_A(pAppliedAttr, AttrFlatColourFill)) // flat colour fill?
00988         {
00989             // get the colour attribute
00990             ColourFillAttribute *pColAttr = (ColourFillAttribute *)(pAppliedAttr->GetAttributeValue());
00991 
00992             // set the colour pointer to the doc colour, and the bitmap pointer to NULL
00993             *ppOutBitmap = NULL;
00994             *ppOutColour = pColAttr->GetStartColour();
00995 
00996         }
00997         else if (IS_A(pAppliedAttr, AttrBitmapColourFill)) // bitmap fill
00998         {
00999 
01000             // set the colour pointer to NULL, and the bitmap pointer to the kernel bitmap
01001             *ppOutBitmap = ((AttrFillGeometry *)pAppliedAttr)->GetBitmap();
01002             *ppOutColour = NULL;
01003         }
01004         else
01005             return FALSE;
01006     }
01007     else
01008         return FALSE;
01009 
01010     return TRUE;
01011 }
01012                 
01013 
01014 
01015 /***********************************************************************************************
01016 
01017 >   virtual BOOL OpBackground::Undo()
01018 
01019     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01020     Created:    26/3/97
01021     Inputs:     -
01022     Outputs:    -
01023     Returns:    TRUE if successfull, FALSE otherwise
01024     Purpose:    Called when the op is undone.
01025                 This broadcasts a 'Guidelines changed' layer message
01026     SeeAlso:    -
01027         
01028 ***********************************************************************************************/
01029 
01030 /* BOOL OpBackground::Undo()
01031 {
01032     if (UndoableOperation::Undo())
01033     {
01034         BroadcastGuidelineChanges(pBroadcastLayer);
01035         return TRUE;
01036     }
01037 
01038     return FALSE;
01039 } */
01040 
01041 /***********************************************************************************************
01042 
01043 >   virtual BOOL OpBackground::Redo()
01044 
01045     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01046     Created:    26/3/97
01047     Inputs:     -
01048     Outputs:    -
01049     Returns:    TRUE if successfull, FALSE otherwise
01050     Purpose:    Called when the op is redone.
01051                 This broadcasts a 'Guidelines changed' layer message
01052     SeeAlso:    -
01053         
01054 ***********************************************************************************************/
01055 
01056 /* BOOL OpBackground::Redo()
01057 {
01058     if (UndoableOperation::Redo())
01059     {
01060         BroadcastGuidelineChanges(pBroadcastLayer);
01061         return TRUE;
01062     }
01063 
01064     return FALSE;
01065 } */
01066 
01067 /***********************************************************************************************
01068 
01069 >   static BOOL OpBackground::Init()
01070 
01071     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01072     Created:    26/3/97
01073     Inputs:     -
01074     Outputs:    -
01075     Returns:    TRUE if op successfully declared, FALSE otherwise
01076     Purpose:    Registers an op desc for this op
01077     SeeAlso:    -
01078         
01079 ***********************************************************************************************/
01080 
01081 BOOL OpBackground::Init()
01082 {
01083     BOOL ok = RegisterOpDescriptor(
01084                                     0, 
01085                                     0,
01086                                     CC_RUNTIME_CLASS(OpBackground), 
01087                                     OPTOKEN_BACKGROUND,
01088                                     OpBackground::GetState,
01089                                     0,  /* help ID */
01090                                     0,  /* bubble ID */
01091                                     0   /* bitmap ID */
01092                                     );
01093     return ok;
01094 }
01095 
01096 /***********************************************************************************************
01097 
01098 >   static OpState OpBackground::GetState(String_256* Description, OpDescriptor*)
01099 
01100     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01101     Created:    26/3/97
01102     Inputs:     Description = ptr to place description of why this op can't happen
01103                 pOpDesc     = ptr to the Op Desc associated with this op
01104     Outputs:    -
01105     Returns:    An OpState object
01106     Purpose:    Func for determining the usability of this op
01107     SeeAlso:    -
01108         
01109 ***********************************************************************************************/
01110 
01111 OpState OpBackground::GetState(String_256* Description, OpDescriptor*)
01112 {
01113     OpState State;
01114     return State;
01115 }
01116 
01117 /***********************************************************************************************
01118 
01119 >   static void OpBackground::GetOpName(String_256* OpName)
01120 
01121     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01122     Created:    26/3/97
01123     Inputs:     OpName = ptr to string
01124     Outputs:    OpName contains a description of the op
01125     Returns:    -
01126     Purpose:    Returns a desc of the op.  Mainly used to fill in the menu item for the undo/redo ops. 
01127     SeeAlso:    -
01128         
01129 ***********************************************************************************************/
01130 
01131 void OpBackground::GetOpName(String_256* OpName)
01132 {
01133     *OpName = String_256(_R(IDS_UNDO_SETBACKGROUND));
01134 }
01135 
01136 
01137 #endif // EXCLUDE_FROM_RALPH

Generated on Sat Nov 10 03:44:17 2007 for Camelot by  doxygen 1.4.4