RecalcBoundsAction Class Reference

An action which records the bounding box of a node, and replaces it on Undo, invalidating that area. This action should be added to the action list before modifying the object's bounding box. Please note that for undo and redo to work correctly, after you have modified the bounding box, you should create a RecordBoundsAction object and append that to the action list. This action is the opposite action to Recalc, and the two should always be used in tandem. More...

#include <pathedit.h>

Inheritance diagram for RecalcBoundsAction:

Action ListItem CCObject SimpleCCObject List of all members.

Public Member Functions

 RecalcBoundsAction ()
 Constructor for the action to recalculate bounds of a node.
 ~RecalcBoundsAction ()
virtual ActionCode Execute ()
 Will replace the bounding box of an object, recording the existing bounds.

Static Public Member Functions

static ActionCode Init (Operation *pOp, ActionList *pActionList, NodeRenderableBounded *WhichNode, Action **NewAction)
 This is the function which creates an instance of this action. If there is no room in the undo buffer (which is determined by the base class Init function called within) the function will either return AC_NO_RECORD which means the operation can continue, but no undo information needs to be stored, or AC_OK which means the operation should continue AND record undo information. If the function returns AC_FAIL, there was not enough memory to record the undo information, and the user has decided not to continue with the operation.
static ActionCode DoRecalc (Operation *pOp, ActionList *pActionList, NodeRenderableBounded *WhichNode, BOOL OptimiseRedraw=FALSE)
 This static function makes it a little easier to use this action. It creates an instance of this action and appends it to the action list. Then it invalidates the current view according to the blob rectangle of the object. This function should be called before you do anything to change the bounding box of an object. It will invalidate the view (including blobs) allowing you to manipulate the object to your heart's content. In order to keep undo and redo running, make sure that after you have finished manipulating the object, you call RecordBoundsAction::DoRecord which will not only invalidate the new bounds rectangle of the object (including blobs) but will also make sure that there are the correct actions in the undo list.
static BOOL CauseOptimisedRedraw (NodePath *pChangedPath, Document *pDoc, Spread *pSpread)
 Called by DoRecord and DoRecalc to only invalidate the areas of the screen covered by the parts of the path that have changed. These will have the NeedToRender flag set.

Protected Attributes

NodeRenderableBoundedChangedNode
DocRect OldBounds

Detailed Description

An action which records the bounding box of a node, and replaces it on Undo, invalidating that area. This action should be added to the action list before modifying the object's bounding box. Please note that for undo and redo to work correctly, after you have modified the bounding box, you should create a RecordBoundsAction object and append that to the action list. This action is the opposite action to Recalc, and the two should always be used in tandem.

Author:
Jim_Lynn (Xara Group Ltd) <camelotdev@xara.com>
Date:
11/7/94
See also:
RecordBoundsAction

Definition at line 863 of file pathedit.h.


Constructor & Destructor Documentation

RecalcBoundsAction::RecalcBoundsAction  ) 
 

Constructor for the action to recalculate bounds of a node.

Author:
Jim_Lynn (Xara Group Ltd) <camelotdev@xara.com>
Date:
11/7/94
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
-

Errors: -

See also:
-

Definition at line 9559 of file pathedit.cpp.

09560 {
09561 }

RecalcBoundsAction::~RecalcBoundsAction  ) 
 

Definition at line 9719 of file pathedit.cpp.

09720 {
09721 }


Member Function Documentation

BOOL RecalcBoundsAction::CauseOptimisedRedraw NodePath pChangedPath,
Document pDoc,
Spread pSpread
[static]
 

Called by DoRecord and DoRecalc to only invalidate the areas of the screen covered by the parts of the path that have changed. These will have the NeedToRender flag set.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/04/95
Parameters:
pChangedPath - points to the path to cause a redraw of [INPUTS] pDoc - points to the document containing the path pSpread - points to the spread containing the path
- [OUTPUTS]
Returns:
TRUE if the optimised redraw succeded, FALSE if the entire shape should be redrawn (an error occured)

Errors: -

See also:
RecordBoundsAction::DoRecord, RecalcBoundsAction::DoRecalc

Definition at line 9744 of file pathedit.cpp.

09745 {
09746     // If the shape is filled then we can't optimise
09747     if (pChangedPath->InkPath.IsFilled)
09748         return FALSE;
09749 
09750     // Build an attribute map
09751     CCAttrMap AttribMap(30);
09752     if (!pChangedPath->FindAppliedAttributes(&AttribMap)) 
09753         return FALSE;
09754 
09755     // Get the current linewidth applied to the NodePath
09756     MILLIPOINT LineWidth = 0;
09757     void* pLineWidth = NULL;
09758     AttribMap.Lookup( CC_RUNTIME_CLASS(AttrLineWidth), pLineWidth );
09759     ERROR3IF(pLineWidth == NULL, "Did not find line width attribute");
09760     if (pLineWidth != NULL) 
09761         LineWidth = ((AttrLineWidth*)pLineWidth)->Value.LineWidth;
09762     else
09763         return FALSE;
09764 
09765     // Get the current dash pattern applied to the NodePath
09766     // Can't optimise if it's a dashed line - the pattern shifts around
09767     void* pDashPat = NULL;
09768     AttribMap.Lookup( CC_RUNTIME_CLASS(AttrDashPattern), pDashPat );
09769     ERROR3IF(pDashPat == NULL, "Did not find dash pattern attribute");
09770     if ((pDashPat == NULL) || (((AttrDashPattern*)pDashPat)->Value.DashPattern.Elements != 0) )
09771         return FALSE;
09772 
09773     // Get the current mitre limit applied to the NodePath
09774     MILLIPOINT MitreLimit = 0;
09775     void* pMitreAttr = NULL;
09776     AttribMap.Lookup( CC_RUNTIME_CLASS(AttrMitreLimit),pMitreAttr);
09777     ERROR3IF(pMitreAttr == NULL, "Did not find mitre attribute");
09778     if (pMitreAttr != NULL) 
09779         MitreLimit = ((AttrMitreLimit*)pLineWidth)->Value.MitreLimit;
09780     else
09781         return FALSE;
09782 
09783 
09784     // See if theres a brush attribute applied to the nodepath
09785     AttrBrushType* pAttrBrush = (AttrBrushType*) pChangedPath->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrBrushType));
09786     if (pAttrBrush != NULL && pAttrBrush->GetBrushHandle() != BrushHandle_NoBrush)
09787     {
09788         pAttrBrush->FlushCache();
09789         DocRect Redraw = pAttrBrush->GetAttrBoundingRect(pChangedPath);
09790         pDoc->ForceRedraw(pSpread, Redraw, FALSE, pChangedPath);
09791     }
09792 
09793     // Get the arrowheads applied to the NodePath
09794     AttrEndArrow* pEndArrow = (AttrEndArrow*) pChangedPath->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrEndArrow));
09795     AttrStartArrow* pStartArrow = (AttrStartArrow*) pChangedPath->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrStartArrow));
09796 
09797     // redraw the areas covered by the arrowheads
09798     // PABODGE - only redraw if the arrohead has moved
09799     if (pEndArrow != NULL)
09800     {
09801         DocRect Redraw = pEndArrow->GetAttrBoundingRect(pChangedPath, &AttribMap);
09802         pDoc->ForceRedraw( pSpread, Redraw, FALSE, pChangedPath );
09803     }
09804     if (pStartArrow != NULL)
09805     {
09806         DocRect Redraw = pStartArrow->GetAttrBoundingRect(pChangedPath, &AttribMap);
09807         pDoc->ForceRedraw( pSpread, Redraw, FALSE, pChangedPath );
09808     }
09809 
09810     // PABODGE - should only inflate by mitre limit if mitre join applied!
09811     MILLIPOINT InflationSize = LineWidth + MitreLimit*4;
09812     const INT32 NumPoints = pChangedPath->InkPath.GetNumCoords();
09813     INT32 loop = 0;
09814     INT32 Previous = 0;
09815     PathVerb* Verbs = NULL;
09816     DocCoord* Coords = NULL;
09817     PathFlags* Flags = NULL;
09818     pChangedPath->InkPath.GetPathArrays(&Verbs, &Coords, &Flags);
09819 
09820     if (pChangedPath->InkPath.FindNextEndPoint(&loop))
09821     {
09822         while (loop < NumPoints)
09823         {
09824             // If the need to render flag is set then cause a redraw of this segment
09825             if (Flags[loop].NeedToRender)
09826             {
09827                 // Get the size of the redraw rect
09828                 DocRect Invalid(Coords[Previous], Coords[Previous]);
09829                 while (Previous < loop)
09830                 {
09831                     Previous++;
09832                     Invalid.IncludePoint(Coords[Previous]);
09833                 }
09834     
09835                 // Do the redraw
09836                 Invalid.Inflate(InflationSize);
09837                 pDoc->ForceRedraw( pSpread, Invalid, FALSE, pChangedPath );
09838             }
09839 
09840             // Point to the next endpoint
09841             Previous = loop;
09842             if (!pChangedPath->InkPath.FindNextEndPoint(&loop))
09843                 break;
09844         }
09845     }
09846     else
09847         return FALSE;
09848 
09849     return TRUE;
09850 }

ActionCode RecalcBoundsAction::DoRecalc Operation pOp,
ActionList pActionList,
NodeRenderableBounded WhichNode,
BOOL  OptimiseRedraw = FALSE
[static]
 

This static function makes it a little easier to use this action. It creates an instance of this action and appends it to the action list. Then it invalidates the current view according to the blob rectangle of the object. This function should be called before you do anything to change the bounding box of an object. It will invalidate the view (including blobs) allowing you to manipulate the object to your heart's content. In order to keep undo and redo running, make sure that after you have finished manipulating the object, you call RecordBoundsAction::DoRecord which will not only invalidate the new bounds rectangle of the object (including blobs) but will also make sure that there are the correct actions in the undo list.

Author:
Jim_Lynn (Xara Group Ltd) <camelotdev@xara.com>
Date:
12/7/94
Parameters:
pOp is the currently running operation [INPUTS] pActionList is a pointer ot the action list to which the action should be appended WhichNode is the node we're dealing with here OptimiseRedraw : If this is TRUE and WhichNode is a NodePath then the NeedToRender flags are used to determine the areas of the screen to redraw
- [OUTPUTS]
Returns:
Action code which indicates success or failure to create the action

Errors: -

See also:
RecordBoundsAction::DoRecalc

Definition at line 9639 of file pathedit.cpp.

09643 {
09644     ERROR3IF(OptimiseRedraw && !WhichNode->IsNodePath(),"Can't optimise redraw for a non-path object");
09645 
09646     RecalcBoundsAction* RecAction;
09647     ActionCode Act = RecalcBoundsAction::Init(pOp, pActionList, WhichNode, (Action**)&RecAction);
09648     if (Act != AC_FAIL)
09649     {
09650         // Force a re-draw of the place where the path used to be
09651         Document* pDoc = pOp->GetWorkingDoc();
09652         ERROR2IF( pDoc == NULL, AC_FAIL, "There was no current document in RecordBoundsAction::DoRecord" );
09653         Spread* pSpread = WhichNode->FindParentSpread();
09654         DocRect Invalid;
09655 
09656         ((NodePath*)WhichNode)->ReleaseCached();
09657         
09658         // Do an optimised redraw if possible
09659         if (WhichNode->IsNodePath() && OptimiseRedraw)
09660             OptimiseRedraw = CauseOptimisedRedraw((NodePath*)WhichNode, pDoc, pSpread);
09661         else
09662             OptimiseRedraw = FALSE;
09663 
09664         if (!OptimiseRedraw)
09665             pDoc->ForceRedraw( pSpread, WhichNode->GetUnionBlobBoundingRect());
09666     }
09667     return Act;
09668 }

ActionCode RecalcBoundsAction::Execute  )  [virtual]
 

Will replace the bounding box of an object, recording the existing bounds.

Author:
Jim_Lynn (Xara Group Ltd) <camelotdev@xara.com>
Date:
11/7/94
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
ActionCode, either AC_OK, AC_NORECORD or AC_FAIL

Errors: -

See also:
-

Reimplemented from Action.

Definition at line 9686 of file pathedit.cpp.

09687 {
09688     // This is undoing a bounds recalculation
09689     
09690     RecordBoundsAction* ReAction;
09691     
09692     // Create a redo action for this action, which is also a RecalcBoundsAction
09693 
09694     ActionCode Act;
09695     Act = RecordBoundsAction::Init(pOperation, 
09696                                     pOppositeActLst, 
09697                                     ChangedNode,
09698                                     (Action**)(&ReAction));
09699     if (Act == AC_FAIL)
09700         return AC_FAIL;
09701 
09702     // Force a re-draw of the place where the path used to be
09703     Document* pDoc = GetWorkingDoc();
09704     ERROR2IF( pDoc == NULL, AC_FAIL, "There was no current document when undoing RecalcBounds" );
09705     Spread* pSpread = ChangedNode->FindParentSpread();
09706     
09707     if (pSpread != NULL)
09708     {
09709         DocRect Invalid = ChangedNode->GetUnionBlobBoundingRect();
09710         pDoc->ForceRedraw( pSpread, Invalid, FALSE, ChangedNode );
09711 
09712         // Mark the bounding rect as invalid
09713         ChangedNode->InvalidateBoundingRect();
09714     }
09715     
09716     return Act;
09717 }

ActionCode RecalcBoundsAction::Init Operation pOp,
ActionList pActionList,
NodeRenderableBounded WhichNode,
Action **  NewAction
[static]
 

This is the function which creates an instance of this action. If there is no room in the undo buffer (which is determined by the base class Init function called within) the function will either return AC_NO_RECORD which means the operation can continue, but no undo information needs to be stored, or AC_OK which means the operation should continue AND record undo information. If the function returns AC_FAIL, there was not enough memory to record the undo information, and the user has decided not to continue with the operation.

Author:
Jim_Lynn (Xara Group Ltd) <camelotdev@xara.com>
Date:
11/7/94
Parameters:
pOp is the pointer to the operation to which this action belongs [INPUTS] pActionList is the action list to which this action should be added WhichNode is the object whose bounds we want to recalculate
NewAction is a pointer to a pointer to an action, allowing the function to return [OUTPUTS] a pointer to the created action
Returns:
ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL

Errors: -

See also:
Action::Init()

Definition at line 9591 of file pathedit.cpp.

09595 {
09596     UINT32 ActSize = sizeof(RecalcBoundsAction);
09597 
09598     ActionCode Ac = Action::Init( pOp, pActionList, ActSize, CC_RUNTIME_CLASS(RecalcBoundsAction), NewAction);
09599     if ((Ac == AC_OK) && (*NewAction != NULL))
09600     {
09601         ((RecalcBoundsAction*)*NewAction)->ChangedNode = WhichNode;
09602         ((RecalcBoundsAction*)*NewAction)->OldBounds = WhichNode->GetBoundingRect();
09603     }
09604 
09605     return Ac;
09606 }


Member Data Documentation

NodeRenderableBounded* RecalcBoundsAction::ChangedNode [protected]
 

Definition at line 883 of file pathedit.h.

DocRect RecalcBoundsAction::OldBounds [protected]
 

Definition at line 884 of file pathedit.h.


The documentation for this class was generated from the following files:
Generated on Sat Nov 10 04:00:20 2007 for Camelot by  doxygen 1.4.4