00001 // $Id: ndoptmz.cpp 1282 2006-06-09 09:46:49Z 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 /* 00099 //*/ 00100 00101 // The implementation of the NodeRenderableInk attribute optimisation routines 00102 00103 #include "camtypes.h" 00104 //#include "node.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00105 //#include "nodeattr.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00106 //#include "list.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00107 //#include "listitem.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00108 //#include "errors.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00109 //#include "ensure.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00110 #include "objreg.h" 00111 #include "ndoptmz.h" 00112 //#include "ink.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00113 #include "nodetext.h" 00114 #include "nodedoc.h" 00115 #include "ndmldgrp.h" 00116 #include "nodemldr.h" 00117 //#include "attrmgr.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00118 00119 // for the template attribute 00120 //#include "cxfrech.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00121 //#include "attrval.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00122 #include "userattr.h" 00123 #include "tmpltatr.h" 00124 00125 #include "brshattr.h" 00126 #include "dbugtree.h" 00127 00128 00129 DECLARE_SOURCE("$Revision: 1282 $"); 00130 CC_IMPLEMENT_DYNCREATE( FactorOutCommonChildAttrAct, Action ) 00131 CC_IMPLEMENT_DYNCREATE( LocaliseCommonAttrAct, Action ) 00132 00133 // Declare smart memory handling in Debug builds 00134 #define new CAM_DEBUG_NEW 00135 00136 00137 00138 00139 /******************************************************************************************** 00140 00141 > BOOL NodeRenderableInk::MakeAttributeComplete(Node* Root = NULL, 00142 BOOL CheckForDuplicates = TRUE, 00143 AttrTypeSet* pAffectedAttrTypes = NULL, 00144 BOOL IncludeDefaults = FALSE, 00145 BOOL bIncludeEffectAttrs = FALSE) 00146 00147 Author: Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com> 00148 Created: 7/2/94 00149 00150 Inputs: Root: The search for attributes will stop at this node. The 00151 NULL default value means 'don't stop until we reach the top'. 00152 CheckForDuplicates: When TRUE a check is made to ensure that duplicate 00153 attribiutes are not added to the subtree (this is the 00154 default). When localising a groups attributes this 00155 check will be unneccessary. 00156 pAffectedAttrTypes: An optional set of attribute types. If this is specified 00157 then we only add attributes which have a type 00158 in this set. 00159 IncludeDefaults: When TRUE default attributes will be added. 00160 bIncludeEffectAttrs Only used when forcing effect attrs to become normal attrs 00161 (see Ungroup) TRUE to force attr scanning to find effect 00162 attrs as well as normal ones... 00163 00164 Outputs: - 00165 Returns: TRUE if successful 00166 FALSE if we run out of memory, the children of the node will remain unchanged 00167 00168 Purpose: This function should be called on a subtree prior to it being moved, either 00169 to a new position in the document, or to another document. It is also used 00170 to localise attributes; during an ungroup for example. 00171 00172 It finds ALL attributes which are required by the subtree and adds 00173 them as first children. 00174 00175 After the subtree has been moved to its new position, the function 00176 NodeRenderableInk::NormaliseAttributes should be called. 00177 00178 SeeAlso: NodeRenderableInk::NormaliseAttributes 00179 SeeAlso: Range::MakeAttributeComplete 00180 00181 ********************************************************************************************/ 00182 00183 BOOL NodeRenderableInk::MakeAttributeComplete(Node* Root, 00184 BOOL CheckForDuplicates, /* = TRUE */ 00185 AttrTypeSet* pAffectedAttrTypes, /* = NULL */ 00186 BOOL IncludeDefaults, /* = FALSE */ 00187 BOOL bIncludeEffectAttrs /* = FALSE */) 00188 { 00189 Node* Current = NULL; // Pointer to the current node in the tree 00190 00191 NodeAttribute* CurAttr; 00192 CCRuntimeClass* AttrType; 00193 BOOL Exists; 00194 00195 Node* PreFirstChild = FindFirstChild(); // Remember the FirstChild of the node before we add 00196 // any new attributes, this will come in handy if we 00197 // need to abort. 00198 00199 // Loop until all attributes are copied, we are not interested in the defaults cos these are the 00200 // same for all docs !. 00201 if (bIncludeEffectAttrs) 00202 Current = NodeAttribute::FindFirstAppliedAttr(this, Root); 00203 else 00204 Current = NodeAttribute::FindPrevAppliedAttr(this, Root); 00205 00206 while (Current && (IncludeDefaults || (!(IS_A(Current->FindParent(), NodeDocument)))) ) 00207 { 00208 // Find the next node, snaking up the tree 00209 if (Current->IsAnAttribute()) 00210 { 00211 CurAttr = (NodeAttribute*)Current; 00212 if (CurAttr->CanBeAppliedToObject() && CurAttr->ShouldBeOptimized()) 00213 { 00214 AttrType = CurAttr->GetAttributeType(); 00215 00216 BOOL Required = RequiresAttrib(AttrType) || this->IsCompound(); 00217 // Is the attribute required ? 00218 if (Required && (!pAffectedAttrTypes || pAffectedAttrTypes->InSet(AttrType))) 00219 { 00220 Exists = FALSE; 00221 if (CheckForDuplicates) 00222 { 00223 // triggers can have duplicates 00224 if(!CurAttr->CanBeMultiplyApplied()) 00225 { 00226 // Does the node already have this child attribute 00227 Exists = (GetChildAttrOfType(AttrType) != NULL); 00228 } 00229 } 00230 00231 #ifdef _DEBUG 00232 if (!CheckForDuplicates) 00233 { 00234 // If we feel there is no need to check for duplicates then there shouldn't be any ! 00235 if (!CurAttr->CanBeMultiplyApplied()) 00236 { 00237 NodeAttribute* pChildAttr = GetChildAttrOfType(AttrType); 00238 if ((pChildAttr != NULL)) 00239 { 00240 #if DEBUG_TREE 00241 DebugTreeDlg::DumpSubTree(this, 4); 00242 #endif 00243 TRACE(_T("Duplicate Attr found at %x %s\n"), pChildAttr, pChildAttr->GetRuntimeClass()->m_lpszClassName); 00244 } 00245 // ERROR3IF((pChildAttr != NULL), "MakeAttributeComplete: Duplicate attr found !"); 00246 } 00247 } 00248 #endif 00249 00250 if (!Exists) 00251 { 00252 // Make a copy of the attribute 00253 NodeAttribute* NewAttr = (NodeAttribute*)CurAttr->SimpleCopy(); 00254 00255 if (NewAttr == NULL) 00256 { 00257 goto OutOfMemory; 00258 } 00259 00260 // Now add the attribute to this node 00261 NewAttr->AttachNode(this, FIRSTCHILD, TRUE, FALSE); 00262 } 00263 } 00264 } 00265 } 00266 Current = NodeAttribute::FindPrevAppliedAttr(Current, Root); 00267 00268 // in order to copy brush ink nodes we need to break if the parent is NULL, else is violates 00269 if (Current!=NULL && Current->FindParent() == NULL) 00270 break; 00271 } 00272 00273 return TRUE; 00274 00275 OutOfMemory: 00276 00277 // Delete any new attributes added to the node 00278 Current = FindFirstChild(); 00279 Node* Next; 00280 00281 while (Current != PreFirstChild) 00282 { 00283 ENSURE(Current != NULL, "PreFirstChild could not be found"); 00284 ENSURE(Current->IsAnAttribute(), "Should be a NodeAttribute"); 00285 00286 Next = Current->FindNext(); 00287 // Delete the attribute 00288 Current->CascadeDelete(); 00289 delete Current; 00290 00291 Current = Next; 00292 } 00293 00294 return FALSE; 00295 } 00296 00297 /******************************************************************************************** 00298 00299 > void NodeRenderableInk::NormaliseAttributes() 00300 00301 Author: Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com> 00302 Created: 9/2/94 00303 Inputs: - 00304 Outputs: - 00305 Returns: - 00306 Purpose: This function should be called whenever an attribute-complete node is inserted 00307 into the tree (whether it's a new node, or a node which has been moved 00308 from elsewhere). 00309 00310 It removes all child attributes of the node which are the same type and value 00311 as attributes defined further up the tree eg. the defaults 00312 00313 Errors: - 00314 SeeAlso: NodeRenderableInk::MakeAttributeComplete 00315 00316 ********************************************************************************************/ 00317 00318 void NodeRenderableInk::NormaliseAttributes() 00319 { 00320 00321 NodeAttribute* ChildAttribute; 00322 NodeAttribute* GlobalAttribute; 00323 00324 Node* LocalScan; 00325 Node* NextLocal; 00326 00327 // Scan the child attribute block 00328 LocalScan = FindFirstChild(); 00329 // Stop if we hit an object or if there are no more children 00330 // NOTE: Stopping scanning when we find the first RendereblInk node prevents 00331 // Effect attributes being Normalised. THIS IS DELIBERATE! 00332 while((LocalScan != NULL) && (!LocalScan->IsAnObject())) 00333 { 00334 // Hand over hand (LocalScan may get deleted) 00335 NextLocal = LocalScan->FindNext(); 00336 if(LocalScan->IsAnAttribute() && ((NodeAttribute*)LocalScan)->ShouldBeOptimized()) // cos it could be a NodeHidden 00337 { 00338 ChildAttribute = (NodeAttribute*)LocalScan; 00339 // We now need to search up the tree to see if ChildAttribute is redundant 00340 // Node* GlobalScan = FindPreviousEffectiveNode(); 00341 Node* GlobalScan = NodeAttribute::FindPrevAppliedAttr(this); 00342 // Search until we can go no higher 00343 while (GlobalScan != NULL) 00344 { 00345 if (GlobalScan->IsAnAttribute()) 00346 { 00347 GlobalAttribute = (NodeAttribute*)GlobalScan; 00348 // An attribute has been found, is it the same class as ChildAttribute ? 00349 if(GlobalAttribute->GetRuntimeClass() == 00350 ChildAttribute->GetRuntimeClass()) 00351 { 00352 // Yes it is, so let's check if they are equal 00353 if ((*GlobalAttribute)==(*ChildAttribute)) 00354 { 00355 // They are equal so we can nuke the child object because it's 00356 // redundant 00357 ChildAttribute->CascadeDelete(); 00358 delete ChildAttribute; 00359 } 00360 break; // don't search any further 00361 } 00362 00363 } 00364 // GlobalScan = GlobalScan->FindPreviousEffectiveNode(); // climb higher 00365 GlobalScan = NodeAttribute::FindPrevAppliedAttr(GlobalScan); 00366 } 00367 } 00368 LocalScan = NextLocal; // Get the next child 00369 } 00370 00371 } 00372 00373 /******************************************************************************************** 00374 00375 > void NodeRenderableInk::RemoveSuperfluousAttribs() 00376 00377 Author: Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com> 00378 Created: 9/2/94 00379 Inputs: - 00380 Outputs: - 00381 Returns: - 00382 Purpose: This fn does not exist. 00383 00384 00385 This function removes attributes from the subtree that we consider to 00386 be superfluous. An attribute is classed as superfluous if - 00387 00388 a. It is overridden by an attribute of the same class before any ink object 00389 has been rendered. 00390 00391 e.g. Select a red pen, select a green pen, draw a circle 00392 00393 Here picking up the red pen is a waste of effort and so can be removed. 00394 00395 A subtree which has had the MakeAttributeComplete method called on it 00396 will probably have attributes like these. 00397 00398 b. The attribute (i.e. same class, same value) has already been defined 00399 00400 e.g. Select a red pen, draw a circle, select a red pen, draw a square 00401 00402 Again the default attributes which will be added by the MakeAttributeComplete 00403 method will fall into this category. 00404 00405 Scope: protected 00406 Errors: - 00407 SeeAlso: NodeRenderableInk::NormaliseAttributes 00408 SeeAlso: NodeRenderableInk::MakeAttributeComplete 00409 00410 ********************************************************************************************/ 00411 /* 00412 void NodeRenderableInk::RemoveSuperfluousAttribs() 00413 { 00414 // Local Scan is used to perform a depth first traversal of the subtree 00415 Node* LocalScan = FindFirstDepthFirst(); 00416 00417 // Global Scan is used to find attributes defined in and above the subtree 00418 Node* GlobalScan; 00419 00420 Node* ToDie = NULL; 00421 00422 // Attribute override flag. This gets set to true when we start processing each 00423 // local attribute. 00424 BOOL AttribOver; 00425 00426 // Traverse the tree in render order 00427 while (LocalScan != NULL) 00428 { 00429 if (LocalScan->IsKindOf(CC_RUNTIME_CLASS(NodeAttribute))) 00430 { 00431 // Ok weve found a node attribute, lets see if it's superfluous 00432 // We need to search back up the tree in reverse render order to determine this 00433 00434 GlobalScan = LocalScan; 00435 00436 // This flag gets set to FALSE as soon as we find an ink node or we move 00437 // to a parent node. 00438 AttribOver = TRUE; 00439 00440 while (GlobalScan != NULL) 00441 { 00442 // Find the next node 00443 if (GlobalScan->FindPrevious() != NULL) 00444 { 00445 GlobalScan = GlobalScan->FindPrevious(); // Search leftmost siblings of 00446 // the subtree first 00447 } 00448 else 00449 { 00450 GlobalScan = GlobalScan->FindParent(); // then move to the parent 00451 AttribOver = FALSE; 00452 } 00453 00454 if (ToDie != NULL) 00455 { 00456 // Set at (a) 00457 ToDie->UnlinkNodeFromTree(); 00458 delete ToDie; 00459 ToDie = NULL; 00460 } 00461 00462 if (GlobalScan != NULL) 00463 { 00464 if (AttribOver) 00465 { 00466 if (GlobalScan->IsKindOf(CC_RUNTIME_CLASS(NodeRenderableInk))) 00467 { 00468 AttribOver = FALSE; 00469 } 00470 } 00471 else if (GlobalScan->GetRuntimeClass() == LocalScan->GetRuntimeClass()) 00472 { 00473 #if _DEBUG 00474 if (IsUserName("Simon")) 00475 { 00476 TRACE( _T("Local attrib = %s, Global = %s"), LocalScan->Name(), GlobalScan->Name()); 00477 } 00478 #endif 00479 00480 if (AttribOver) 00481 { 00482 // The GlobalScan Attribute is redundant 00483 // (a) 00484 ToDie = GlobalScan; 00485 // continue the search 00486 } 00487 00488 // An attribute of the same class is found, do they have the 00489 // same value 00490 00491 else if ( (*((NodeAttribute*)LocalScan)) == (*((NodeAttribute*)GlobalScan))) 00492 { 00493 // The attribute is superfluous so kill it 00494 //(b) 00495 ToDie = LocalScan; 00496 break;// Terminate the global scan 00497 } 00498 00499 } 00500 } 00501 } 00502 } 00503 // Get the next node in the subtree 00504 LocalScan = LocalScan->FindNextDepthFirst(this); 00505 00506 if (ToDie != NULL) 00507 { 00508 // Set at (b) 00509 ToDie->UnlinkNodeFromTree(); 00510 delete ToDie; 00511 ToDie = NULL; 00512 } 00513 } 00514 } 00515 */ 00516 00517 00518 /******************************************************************************************** 00519 00520 > static BOOL NodeRenderableInk::FindCommonAttributesToFactorOut(CommonAttrSet* CommonAttributeSet) 00521 00522 Author: Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com> 00523 Created: 3/8/94 00524 Inputs: - 00525 Outputs: All items in the CommonAttributeSet are attributes common to all objects 00526 within the group. The attributes applied to objects which can discard their 00527 attributes (like the caret) are ignored 00528 00529 Returns: TRUE if successful, FALSE otherwise (out of memory) 00530 Purpose: Finds all attributes common to the compound node 00531 Errors: - 00532 Scope: private 00533 SeeAlso: - 00534 00535 ********************************************************************************************/ 00536 /* 00537 Technical Notes: 00538 00539 (Method) 00540 00541 CommonAttributeSet = the set of all attributes 00542 Each attribute in the set has a NULL value. 00543 00544 Scan all grouped objects (Current) 00545 Scan each attribute in the common attribute set in turn (CommonA) 00546 If Current requires the attribute 00547 If Current has an attribute with the same type as CommonA then 00548 If CommonA == NULL 00549 CommonA = Currents attribute 00550 Else if (CommonA != Currents attribute) 00551 The attribute is not common so remove it from the common attribute set. 00552 else 00553 The attribute is not common so remove it from the common attribute set. 00554 EndScan 00555 Current = Next object in group 00556 EndScan 00557 */ 00558 00559 BOOL NodeRenderableInk::FindCommonAttributesToFactorOut(CommonAttrSet* CommonAttributeSet) 00560 { 00561 CommonAttributeItem* CommonAttrItem; 00562 CommonAttributeItem* NextCommonAttrItem; 00563 00564 // Place all attributes in the CommonAttributeSet 00565 if (!CommonAttributeSet->AddAllTypesToSet()) 00566 { 00567 return FALSE; // ERROR already called 00568 } 00569 00570 // Scan all grouped objects 00571 for (Node* CurrentObject = FindFirstChild(); 00572 CurrentObject != NULL; 00573 CurrentObject = CurrentObject->FindNext()) 00574 { 00575 if (CurrentObject->IsAnObject()) 00576 { 00577 00578 // Scan all attributes in the CommonAttributeSet in turn 00579 CommonAttrItem = (CommonAttributeItem*)CommonAttributeSet->GetHead(); 00580 00581 while(CommonAttrItem != NULL) 00582 { 00583 // Hand over hand cos we may well delete the CommonAttrItem 00584 NextCommonAttrItem = (CommonAttributeItem*)(CommonAttributeSet->GetNext(CommonAttrItem)); 00585 00586 // Does CurrentObject require the attribute to render 00587 if ( (((NodeRenderableInk*)CurrentObject)->RequiresAttrib(CommonAttrItem->AttrType)) || CurrentObject->IsCompound()) 00588 { 00589 BOOL DeleteCommonAttr = FALSE; // Until we know better 00590 00591 // Ok the current object requires the attribute 00592 // Does the CurrentObject have a child attribute of this type ? 00593 NodeAttribute* pAttrNode = 00594 ((NodeRenderableInk*)CurrentObject)->GetChildAttrOfType(CommonAttrItem->AttrType); 00595 if (pAttrNode != NULL && pAttrNode->ShouldBeOptimized()) 00596 { 00597 // Ok it has an attribute of this type 00598 if (CommonAttrItem->pAttr == NULL) 00599 { 00600 // The attribute becomes a common attribute 00601 CommonAttrItem->pAttr = pAttrNode; 00602 CommonAttrItem->Status = Range::ATTR_COMMON; 00603 } 00604 else if(CommonAttrItem->pAttr->GetRuntimeClass() == 00605 pAttrNode->GetRuntimeClass()) 00606 { 00607 // Ok they are the same runtime class but are they equal 00608 if (!((*pAttrNode)==(*(CommonAttrItem->pAttr)))) 00609 { 00610 // They are not equal so remove CommonAttrItem from the 00611 // common attribute set. 00612 DeleteCommonAttr = TRUE; 00613 } 00614 // DY 12/5/2000 AttrBrushTypes cannot be factored because they 00615 // may contain caches of pressure or timestamp data which apply 00616 // to a specific node only. 00617 // They no longer contain this data so factor them like normal! 00618 //if (pAttrNode->IsKindOf(CC_RUNTIME_CLASS(AttrBrushType))) 00619 // DeleteCommonAttr = TRUE; 00620 } 00621 else 00622 { 00623 // They cannot be the same value cos they are different runtime types 00624 DeleteCommonAttr = TRUE; 00625 } 00626 } 00627 else 00628 { 00629 // The CurrentObject does not have an attribute of this type so it 00630 // cannot be common 00631 DeleteCommonAttr = TRUE; 00632 } 00633 00634 if (DeleteCommonAttr) 00635 { 00636 delete(CommonAttributeSet->RemoveItem(CommonAttrItem)); 00637 } 00638 } 00639 00640 CommonAttrItem = NextCommonAttrItem; 00641 } 00642 } 00643 // Removed because there are circumstances where certain attributes have 00644 // already been factored out eg. Corel filter 00645 //else 00646 //{ 00647 // ENSURE(CurrentObject->GetRuntimeClass() == CC_RUNTIME_CLASS(NodeHidden), 00648 // "It's not an object, it's not a hidden node, so what is it ??"); 00649 //} 00650 } 00651 // Delete all NULL items in the CommonAttributeSet 00652 CommonAttrItem = (CommonAttributeItem*)CommonAttributeSet->GetHead(); 00653 while (CommonAttrItem != NULL) 00654 { 00655 CommonAttributeItem* Next = (CommonAttributeItem*)CommonAttributeSet->GetNext(CommonAttrItem); 00656 if (CommonAttrItem->pAttr == NULL) 00657 { 00658 // Item is a non required attribute so zap it 00659 delete (CommonAttributeSet->RemoveItem(CommonAttrItem)); 00660 } 00661 CommonAttrItem = Next; 00662 } 00663 00664 return TRUE; // Job done 00665 } 00666 00667 00668 00669 00670 /******************************************************************************************** 00671 00672 > static BOOL NodeRenderableInk::FactorOutCommonChildAttributes(BOOL Global = FALSE, 00673 AttrTypeSet* pAffectedAttrTypes = NULL) 00674 00675 Author: Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com> 00676 Created: 2/8/94 00677 00678 Inputs: Global: When TRUE we recursively factor out attributes in all parent compounds 00679 of the CompoundObject (Bottom up) 00680 00681 pAffectedAttrTypes: An optional set of attribute types. If this is specified 00682 then we only consider factoring out those attributes 00683 which have a type which is in this set. 00684 00685 Outputs: TRUE if successful, FALSE otherwise (out of memory) 00686 00687 Returns: This function finds all attributes which are common to all children 00688 of this compound object, adds the common attributes to this node and 00689 deletes them from its children. 00690 00691 If the compound contains a node which can discard its attributes (like the caret) 00692 then its attributes are not considered when factoring out. 00693 00694 00695 Purpose: 00696 Scope: public 00697 Errors: - 00698 Document: atroptmz.doc 00699 SeeAlso: - 00700 00701 ********************************************************************************************/ 00702 00703 BOOL NodeRenderableInk::FactorOutCommonChildAttributes(BOOL Global, AttrTypeSet* pAffectedAttrTypes) 00704 { 00705 // This function should only ever get called on a compound object 00706 ENSURE(IsCompound(), "FactorOutCommonChildAttributes called on a non compound object"); 00707 00708 00709 // Try to factor out the neccessary attributes 00710 if (!FactorOutCommonChildAttrHelper(Global, pAffectedAttrTypes)) 00711 { 00712 // Tidyup then return FAIL 00713 DeleteLocalisedAttributes(Global, pAffectedAttrTypes); // tidyup 00714 return FALSE; // Failed 00715 } 00716 else 00717 { 00718 // The only thing that remains now is to delete all remaining factored out attributes 00719 DeleteFactoredOutAttribs(Global, pAffectedAttrTypes); 00720 } 00721 00722 return TRUE; // Success 00723 } 00724 00725 /******************************************************************************************** 00726 00727 > BOOL NodeRenderableInk::FactorOutCommonChildAttributesHelper(BOOL Global, 00728 AttrTypeSet* pAffectedAttrTypes) 00729 00730 00731 Author: Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com> 00732 Created: 17/5/95 00733 Inputs: Global: When TRUE we recursively factor out attributes in all parent compounds 00734 of the CompoundObject (Bottom up) 00735 00736 pAffectedAttrTypes: An optional set of attribute types. If this is specified 00737 then we only consider factoring out those attributes 00738 which have a type which is in this set. 00739 Outputs: - 00740 Returns: - 00741 Purpose: This is a helper function for FactorOutCommonChildAttributes. It finds all 00742 attributes which are common to all children of this compound object and 00743 adds the common attributes to this node. If Global is TRUE then it recursivly 00744 tries to factor out the attributes on all parent compounds. This function 00745 does not delete the attributes which are factored out, This is left to 00746 the calling function. 00747 00748 Errors: - 00749 SeeAlso: - 00750 00751 ********************************************************************************************/ 00752 00753 BOOL NodeRenderableInk::FactorOutCommonChildAttrHelper(BOOL Global, AttrTypeSet* pAffectedAttrTypes) 00754 { 00755 // This function should only ever get called on a compound object 00756 ENSURE(IsCompound(), "FactorOutCommonChildAttributes called on a non compound object"); 00757 00758 CommonAttrSet CommonAttributeSet; // A list of CommonAttributeItems 00759 00760 if (!FindCommonAttributesToFactorOut(&CommonAttributeSet)) // Ignores attr discard nodes 00761 { 00762 return FALSE; 00763 } 00764 00765 NodeAttribute* pFactoredOutAttr; 00766 00767 // Ok let's add the common attributes to the first child of the group 00768 CommonAttributeItem* pCommonAttr; 00769 for (pCommonAttr = (CommonAttributeItem*)CommonAttributeSet.GetHead(); 00770 pCommonAttr != NULL; 00771 pCommonAttr = (CommonAttributeItem*)CommonAttributeSet.GetNext(pCommonAttr)) 00772 { 00773 // Is the common attribute an attribute which should be factored out ? 00774 if (!pAffectedAttrTypes || (pAffectedAttrTypes->InSet(pCommonAttr->pAttr->GetAttributeType())) ) 00775 { 00776 //pCommonAttr->pAttr->MoveNode(this, FIRSTCHILD); 00777 // Take a copy of the node and insert it as a first child 00778 pFactoredOutAttr = (NodeAttribute*)(pCommonAttr->pAttr->SimpleCopy()); 00779 if (!pFactoredOutAttr) 00780 return FALSE; 00781 pFactoredOutAttr->AttachNode(this, FIRSTCHILD, TRUE, FALSE); 00782 } 00783 } 00784 00785 // The CommonAttributeSet is no longer required 00786 CommonAttributeSet.DeleteAll(); 00787 00788 // Do we need to factor out the parents attributes ? 00789 if (Global) 00790 { 00791 Node* pParent = FindParent(); 00792 if (pParent && (pParent->IsCompound())) 00793 { 00794 // We need to localise the parent's attributes first (Recursive bit) 00795 if (!(((NodeRenderableInk*)pParent)->FactorOutCommonChildAttrHelper(TRUE, pAffectedAttrTypes))) 00796 { 00797 return FALSE; // Failed 00798 } 00799 } 00800 } 00801 return TRUE; // Success 00802 } 00803 00804 00805 /******************************************************************************************** 00806 00807 > BOOL NodeRenderableInk::LocaliseCommonAttributes(BOOL CheckForDuplicates = FALSE, 00808 BOOL Global = FALSE, 00809 AttrTypeSet* pAffectedAttrTypes = NULL, 00810 BOOL RecursiveForChildren = FALSE); 00811 00812 Author: Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com> 00813 Created: 4/8/94 00814 00815 Inputs: CheckForDuplicates: This should be TRUE if the children of this compound 00816 node could have child attributes with the same 00817 type as the compound's attributes. This should never 00818 be the case. 00819 00820 Global: TRUE indicates that we should localise the attributes on all 00821 parent compound nodes (top down), before localising the attributes for 00822 this compound. 00823 00824 00825 pAffectedAttrTypes: An optional set of attribute types. If this is specified 00826 then we only consider localising those attributes 00827 which have a type which is in this set. 00828 RecursiveForChildren: Passed onto the helper function, means that if we have children 00829 who are compound then they will have LocaliseCommonAttrs called on 00830 them also 00831 Outputs: - 00832 Returns: TRUE if successful 00833 FALSE if we run out of memory, in this situation the NodeRenderableInk is left unchanged 00834 00835 Purpose: This function is the opposite of the FactorOutCommonChildAttributes function 00836 it copies all attributes common to the compound to each child object within the 00837 compound which requires each attribute. The groups common attributes are deleted. 00838 00839 The routine does not localise attributes on objects which can discard their child 00840 attributes (like the caret) 00841 00842 Errors: - 00843 SeeAlso: NodeRenderableInk::FactorOutCommonChildAttributes 00844 00845 ********************************************************************************************/ 00846 00847 BOOL NodeRenderableInk::LocaliseCommonAttributes(BOOL CheckForDuplicates, 00848 BOOL Global, 00849 AttrTypeSet* pAffectedAttrTypes, 00850 BOOL RecursiveForChildren) 00851 { 00852 // This function should only ever get called on a compound object 00853 ENSURE(IsCompound(), "LocaliseCommonAttributes called on a non compound object"); 00854 00855 // First of all let's try and localise the attributes. This is the bit that can fail 00856 if (!LocaliseCommonAttrHelper(CheckForDuplicates, Global, pAffectedAttrTypes, RecursiveForChildren)) 00857 { 00858 // We ran out of memory so we must, delete all attributes which were localised 00859 DeleteFactoredOutAttribs(Global, pAffectedAttrTypes); 00860 return FALSE; 00861 } 00862 else 00863 { 00864 // We managed to localise all the attributes so it is now safe to delete 00865 // them from the compounds. 00866 DeleteLocalisedAttributes(Global, pAffectedAttrTypes); 00867 return TRUE; 00868 } 00869 } 00870 00871 /******************************************************************************************** 00872 00873 > BOOL NodeRenderableInk::LocaliseCommonAttrHelper(BOOL CheckForDuplicates, 00874 BOOL Global, 00875 AttrTypeSet* pAffectedAttrTypes, 00876 BOOL RecursiveDownwards) 00877 00878 00879 Author: Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com> 00880 Created: 16/5/95 00881 00882 Inputs: CheckForDuplicates: This should be TRUE if the children of this compound 00883 node could have child attributes with the same 00884 type as the compound's attributes. This should never 00885 be the case. 00886 00887 Global: TRUE indicates that we should localise the attributes on all 00888 parent compound nodes (top down), before localising the attributes for 00889 this compound. 00890 00891 00892 pAffectedAttrTypes: An optional set of attribute types. If this is specified 00893 then we only consider localising those attributes 00894 which have a type which is in this set. 00895 RecursiveDownwards: Passed on to the attribute helper, means that if we have a child 00896 who is also compound then we will also localise their attributes. 00897 Defaults to FALSE. 00898 00899 Outputs: - 00900 Returns: TRUE if successful 00901 FALSE if we run out of memory, the localised attributes are not deleted 00902 in this function. 00903 00904 Purpose: This function copies all attributes common to the compound to each child object 00905 within the compound which requires each attribute. 00906 00907 The routine does not localise attributes on objects which can discard their child 00908 attributes (like the caret) 00909 00910 00911 Scope: private 00912 00913 SeeAlso: NodeRenderableInk::LocaliseCommonAttributes 00914 00915 ********************************************************************************************/ 00916 00917 00918 BOOL NodeRenderableInk::LocaliseCommonAttrHelper(BOOL CheckForDuplicates, 00919 BOOL Global, 00920 AttrTypeSet* pAffectedAttrTypes, 00921 BOOL RecursiveForChildren) 00922 { 00923 // Do we need to globally optimise ? 00924 if (Global) 00925 { 00926 Node* pParent = FindParent(); 00927 if (pParent && (pParent->IsCompound())) 00928 { 00929 // We need to localise the parent's attributes first (Recursive bit) 00930 if (!(((NodeRenderableInk*)pParent)->LocaliseCommonAttrHelper(CheckForDuplicates, TRUE, pAffectedAttrTypes))) 00931 { 00932 return FALSE; // Failed 00933 } 00934 } 00935 } 00936 00937 // add all necessary attrs to each child object in the group 00938 for (Node* Current=FindFirstChild(); Current!=NULL; Current=Current->FindNext()) 00939 { 00940 if (RecursiveForChildren && Current->IsCompound()) 00941 ((NodeRenderableInk*)Current)->LocaliseCommonAttributes(FALSE, FALSE, NULL, TRUE); 00942 00943 if (Current->IsAnObject()) 00944 { 00945 NodeRenderableInk* pObject = (NodeRenderableInk*)Current; 00946 BOOL ChkForDups = CheckForDuplicates; 00947 Node* pRoot = RecursiveForChildren ? NULL : this; 00948 if(!pObject->MakeAttributeComplete(pRoot,ChkForDups,pAffectedAttrTypes)) 00949 return FALSE; // out of memory 00950 } 00951 } 00952 00953 return TRUE; 00954 } 00955 00956 /******************************************************************************************** 00957 00958 > void NodeRenderableInk::DeleteLocalisedAttributes(BOOL Global = FALSE 00959 AttrTypeSet* pAffectedAttrTypes) 00960 00961 Author: Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com> 00962 Created: 16/5/95 00963 00964 Inputs: Global: TRUE indicates that we should delete the attributes on all 00965 parent compound nodes as well as this node's attributes 00966 00967 00968 pAffectedAttrTypes: An optional set of attribute types. If this is specified 00969 then we only consider deleting those attributes 00970 which have a type which is in this set. 00971 00972 Scope: private 00973 00974 SeeAlso: NodeRenderableInk::LocaliseCommonAttributes 00975 00976 ********************************************************************************************/ 00977 00978 void NodeRenderableInk::DeleteLocalisedAttributes(BOOL Global, 00979 AttrTypeSet* pAffectedAttrTypes ) 00980 { 00981 // Do we need to delete any parent compound's attributes 00982 if (Global) 00983 { 00984 Node* pParent = FindParent(); 00985 if (pParent && pParent->IsCompound()) 00986 { 00987 // We need to localise the parent's attributes first (Recursive bit) 00988 ((NodeRenderableInk*)pParent)->DeleteLocalisedAttributes(Global, pAffectedAttrTypes); 00989 } 00990 } 00991 00992 00993 // Delete all moved attributes 00994 Node* Next; 00995 Node* Current = FindFirstChild(); 00996 while (Current != NULL && !Current->IsAnObject()) 00997 { 00998 Next = Current->FindNext(); 00999 if (Current->IsAnAttribute()) 01000 { 01001 BOOL DeleteAttr = TRUE; 01002 if (pAffectedAttrTypes) 01003 { 01004 // Only delete the attribute if it has been localised 01005 if (!(pAffectedAttrTypes->InSet(((NodeAttribute*)Current)->GetAttributeType()))) 01006 DeleteAttr = FALSE; 01007 } 01008 if (DeleteAttr) 01009 { 01010 // Die 01011 // Ilan 19/04/00 01012 // More generally speaking, all attributes which returned FALSE in their ShouldBeOptimized() 01013 // calls, will not have been localised to the child nodes during DoLocaliseCommonAttributes(). 01014 // Hence don't want to delete these attributes, they must remain attached to the group node 01015 // which we are ungrouping so that they are present on an UNDO of a OpUngroup 01016 // Attributes in this category include Feather attibutes and TemplateAttributes at present 01017 // if (!Current->IsKindOf(CC_RUNTIME_CLASS(TemplateAttribute))) 01018 if( ((NodeAttribute*)Current)->ShouldBeOptimized()) 01019 { 01020 Current->CascadeDelete(); 01021 delete Current; 01022 } 01023 } 01024 } 01025 Current = Next; 01026 } 01027 } 01028 01029 /******************************************************************************************** 01030 01031 > void NodeRenderableInk::DeleteFactoredOutAttribs(BOOL Global = FALSE 01032 AttrTypeSet* pAffectedAttrTypes) 01033 01034 Author: Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com> 01035 Created: 16/5/95 01036 01037 Inputs: Global: TRUE indicates that we should delete the attributes on all 01038 parent compound nodes as well as this node's attributes 01039 01040 01041 pAffectedAttrTypes: An optional set of attribute types. If this is specified 01042 then we only consider deleting those attributes 01043 which have a type which is in this set. 01044 01045 01046 Purpose: Deletes all child attributes of objects within the compound, which are defined 01047 in the groups child attribute block. The attributes of objects which discard 01048 their child attributes (like the caret) are only deleted if they have the same value 01049 Scope: private 01050 01051 ********************************************************************************************/ 01052 01053 void NodeRenderableInk::DeleteFactoredOutAttribs(BOOL Global, AttrTypeSet* pAffectedAttrTypes) 01054 { 01055 Node* pGroupNode = FindFirstChild(); 01056 while(pGroupNode!=NULL) 01057 { 01058 // Karim 30/08/2000 01059 // Non-optimisable attributes, like feathers and names, 01060 // must not be automatically deleted - only automatically delete optimisable ones. 01061 if (pGroupNode->IsAnAttribute() && ((NodeAttribute*)pGroupNode)->ShouldBeOptimized()) 01062 { 01063 NodeAttribute* pGroupAttr = (NodeAttribute*)pGroupNode; 01064 CCRuntimeClass* GrouptAttrType = pGroupAttr->GetAttributeType(); 01065 if (pAffectedAttrTypes==NULL || pAffectedAttrTypes->InSet(GrouptAttrType)) 01066 { 01067 // delete this group attr type from all child objects of this group 01068 // BUT if obj discards child attrs only delete attr if it also has same value 01069 for (Node* pNode=FindFirstChild(); pNode!=NULL; pNode=pNode->FindNext()) 01070 { 01071 if (pNode->IsAnObject()) 01072 { 01073 NodeRenderableInk* pObject = (NodeRenderableInk*)pNode; 01074 NodeAttribute* pDeadAttr = pObject->GetChildAttrOfType(GrouptAttrType); 01075 if (pDeadAttr!=NULL) 01076 { 01077 // This code used to only test the attribute for equality if pObject 01078 // returned TRUE from DiscardsAttributeChildren, otherwise it would 01079 // just assume that they are identical and delete it. 01080 // The DiscardAttributeChildren checks are now done elsewhere so 01081 // this code now just assumes it can delete any attributes that have 01082 // got this far. 01083 // This optimisation relies on the tree being in a "legal" state 01084 // at the start (i.e. correctly optimised) and also helps to correct 01085 // problems where attributes may have been incorrectly left on children 01086 // (though such "corrections" may change the appearance of the document). 01087 01088 pDeadAttr->CascadeDelete(); 01089 delete pDeadAttr; 01090 } 01091 } 01092 } 01093 } 01094 } 01095 pGroupNode = pGroupNode->FindNext(); 01096 } 01097 01098 // Do we need to delete any parent compound's attributes 01099 if (Global) 01100 { 01101 Node* pParent = FindParent(); 01102 if (pParent && (pParent->IsCompound())) 01103 { 01104 // We need to delete the parent's attributes first (Recursive bit) 01105 ((NodeRenderableInk*)pParent)->DeleteFactoredOutAttribs(Global, pAffectedAttrTypes); 01106 } 01107 } 01108 } 01109 01110 01111 /******************************************************************************************** 01112 01113 > BOOL Node::OptimiseAttributes() 01114 01115 Author: Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com> 01116 Created: 8/8/94 01117 Inputs: - 01118 Outputs: - 01119 Returns: - 01120 Purpose: This function should be called on a subtree 01121 Errors: - 01122 SeeAlso: - 01123 01124 ********************************************************************************************/ 01125 01126 01127 BOOL Node::OptimiseAttributes() 01128 { 01129 Node* Current= this->FindFirstDepthFirst(); 01130 01131 while (Current != NULL) 01132 { 01133 if (Current->IsCompound()) 01134 { 01135 ENSURE(Current->IsKindOf(CC_RUNTIME_CLASS(NodeRenderableInk)), "Compound should be a NodeRenderableInk"); 01136 // It's a compound node, so factor out common attributes 01137 // We don't want to attribute inside moulds (as yet) 01138 if ( !((IS_A(Current, NodeMouldGroup)) || (IS_A(Current, NodeMoulder))) ) 01139 { 01140 if (!((NodeRenderableInk*)Current)->FactorOutCommonChildAttributes()) 01141 { 01142 return FALSE; 01143 } 01144 } 01145 } 01146 Current = Current->FindNextDepthFirst(this); 01147 } 01148 01149 return TRUE; 01150 } 01151 01152 //------------------------------------------------------------------------------------------ 01153 // FactorOutCommonChildAttrAct methods 01154 01155 /******************************************************************************************** 01156 01157 > FactorOutCommonChildAttrAct::FactorOutCommonChildAttrAct() 01158 01159 Author: Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com> 01160 Created: 16/8/93 01161 Inputs: - 01162 Outputs: - 01163 Returns: - 01164 Purpose: FactorOutCommonChildAttrAct constructor 01165 Errors: - 01166 SeeAlso: - 01167 01168 ********************************************************************************************/ 01169 01170 01171 FactorOutCommonChildAttrAct::FactorOutCommonChildAttrAct() 01172 { 01173 } 01174 01175 /******************************************************************************************** 01176 01177 > ActionCode FactorOutCommonChildAttrAct::Execute() 01178 01179 Author: Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com> 01180 Created: 16/8/93 01181 Inputs: - 01182 Outputs: ActionCode indicating if the action was successfully executed or not 01183 Returns: - 01184 Purpose: Executes the FactorOutCommonChildAttrAct which factors out all attributes 01185 which are common to all children of the compound object. All common attributes 01186 become first children of the compound object. 01187 Errors: - 01188 SeeAlso: LocaliseCommonAttrAct 01189 01190 01191 ********************************************************************************************/ 01192 01193 ActionCode FactorOutCommonChildAttrAct::Execute() 01194 { 01195 LocaliseCommonAttrAct* NewAct; 01196 ActionCode ActCode; 01197 01198 // Attempt to initialise the LocaliseCommonAttrAct action which will localise the attributes 01199 if ((ActCode = LocaliseCommonAttrAct::Init(pOperation, 01200 pOppositeActLst, 01201 CompoundObj, 01202 Global, 01203 pSetOfAffectedAttrTypes, 01204 ( Action**)(&NewAct))) != AC_FAIL) 01205 { 01206 if (!CompoundObj->FactorOutCommonChildAttributes(Global, pSetOfAffectedAttrTypes)) 01207 { 01208 return AC_FAIL; 01209 } 01210 } 01211 return (ActCode); 01212 } 01213 01214 /******************************************************************************************** 01215 01216 > static ActionCode FactorOutCommonChildAttrAct::Init(Operation* const pOp, 01217 ActionList* pActionList, 01218 NodeRenderableInk* pCompound, 01219 BOOL Global, 01220 AttrTypeSet* pAffectedAttrTypes, 01221 Action** NewAction); 01222 01223 Author: Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com> 01224 Created: 14/9/93 01225 01226 Inputs: pOp: The operation to which the action should be added 01227 01228 pActionList: The action list in the operation object 01229 01230 pCompound: The compound object 01231 01232 Global: When TRUE the attributes on all parent compounds are also 01233 factored out. 01234 01235 pAffectedAttrTypes: An optional set of attribute types. If this is specified 01236 then we only consider factoring out those attributes 01237 which have a type which is in this set. 01238 01239 01240 Outputs: NewAction: A pointer to the action if it could be allocated. 01241 01242 Returns: AC_FAIL: There was not enough room in the operation history for the 01243 action and the user did not wish to continue. Usually 01244 End() should be called in this situation. 01245 01246 AC_NORECORD: There was not enough room in the operation history for 01247 the action, but the user requested that he wished to 01248 continue without undo. 01249 01250 AC_OK : The action was successfully initialised and added to the 01251 operation. 01252 01253 01254 Purpose: To check that there is sufficient room for the action in the operation 01255 history, and if there is, then to add the action to the operations 01256 action list. 01257 01258 The function calls the Action::Init function passing the runtime class 01259 of a FactorOutCommonChildAttrAct. 01260 Errors: - 01261 SeeAlso: Action::Init 01262 01263 ********************************************************************************************/ 01264 01265 ActionCode FactorOutCommonChildAttrAct::Init(Operation* const pOp, 01266 ActionList* pActionList, 01267 NodeRenderableInk* pCompound, 01268 BOOL global, 01269 AttrTypeSet* pAffectedAttrTypes, 01270 Action** NewAction) 01271 01272 { 01273 ActionCode Ac = (Action::Init(pOp, 01274 pActionList, 01275 sizeof(FactorOutCommonChildAttrAct), 01276 CC_RUNTIME_CLASS(FactorOutCommonChildAttrAct), 01277 NewAction)); 01278 01279 if (*NewAction != NULL) 01280 { 01281 ((FactorOutCommonChildAttrAct*)(*NewAction))->CompoundObj = pCompound; 01282 ((FactorOutCommonChildAttrAct*)(*NewAction))->pSetOfAffectedAttrTypes = pAffectedAttrTypes; 01283 ((FactorOutCommonChildAttrAct*)(*NewAction))->Global = global; 01284 } 01285 01286 return (Ac); 01287 } 01288 01289 /******************************************************************************************** 01290 01291 > virtual void FactorOutCommonChildAttrAct::Slaughter() 01292 01293 Author: Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com> 01294 Created: 24/05/95 01295 Inputs: - 01296 Outputs: - 01297 Returns: - 01298 Purpose: destructor which gets called when an operation is deleted 01299 Errors: - 01300 SeeAlso: Action::Slaughter 01301 01302 ********************************************************************************************/ 01303 01304 void FactorOutCommonChildAttrAct::Slaughter() 01305 { 01306 // Destroy the set of attribute types 01307 if (pSetOfAffectedAttrTypes) 01308 { 01309 pSetOfAffectedAttrTypes->DeleteAll(); 01310 delete pSetOfAffectedAttrTypes; 01311 } 01312 01313 // call the base class to destroy the action 01314 Action::Slaughter(); 01315 } 01316 01317 01318 //------------------------------------------------------------------------------------------ 01319 // LocaliseCommonAttrAct methods 01320 01321 /******************************************************************************************** 01322 01323 > LocaliseCommonAttrAct::LocaliseCommonAttrAct() 01324 01325 Author: Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com> 01326 Created: 16/8/93 01327 Inputs: - 01328 Outputs: - 01329 Returns: - 01330 Purpose: LocaliseCommonAttrAct constructor 01331 Errors: - 01332 SeeAlso: - 01333 01334 ********************************************************************************************/ 01335 01336 01337 LocaliseCommonAttrAct::LocaliseCommonAttrAct() 01338 { 01339 } 01340 01341 /******************************************************************************************** 01342 01343 > ActionCode LocaliseCommonAttrAct::Execute() 01344 01345 Author: Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com> 01346 Created: 16/8/93 01347 Inputs: - 01348 Outputs: ActionCode indicating if the action was successfully executed or not 01349 Returns: - 01350 Purpose: Executes the LocaliseCommonAttrAct which copies all attributes common to the 01351 compound object to each child object within the group which requires each 01352 attribute. The groups common attributes are deleted. 01353 Errors: - 01354 SeeAlso: FactorOutCommonChildAttrAct 01355 01356 01357 ********************************************************************************************/ 01358 01359 ActionCode LocaliseCommonAttrAct::Execute() 01360 { 01361 FactorOutCommonChildAttrAct* NewAct; 01362 ActionCode ActCode; 01363 01364 // Attempt to initialise the FactorOutCommonChildAttrAct action 01365 if ((ActCode = FactorOutCommonChildAttrAct::Init(pOperation, 01366 pOppositeActLst, 01367 CompoundObj, 01368 Global, 01369 pSetOfAffectedAttrTypes, 01370 ( Action**)(&NewAct))) != AC_FAIL) 01371 { 01372 if (!CompoundObj->LocaliseCommonAttributes(TRUE, // Always check for duplicates when undoing 01373 Global, 01374 pSetOfAffectedAttrTypes)) 01375 { 01376 return AC_FAIL; 01377 } 01378 } 01379 return (ActCode); 01380 } 01381 01382 /******************************************************************************************** 01383 01384 > static ActionCode LocaliseCommonAttrAct::Init(Operation* const pOp, 01385 ActionList* pActionList, 01386 NodeRenderableInk* pCompound, 01387 BOOL Global, 01388 AttrTypeSet* pAffectedAttrTypes, 01389 Action** NewAction); 01390 01391 Author: Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com> 01392 Created: 14/9/93 01393 01394 Inputs: pOp: The operation to which the action should be added 01395 01396 pActionList: The action list in the operation object 01397 01398 pCompound: The compound object 01399 01400 01401 Global: TRUE indicates that we should localise the attributes on all 01402 parent compound nodes (top down), before localising the attributes for 01403 this compound. 01404 01405 01406 pAffectedAttrTypes: An optional set of attribute types. If this is specified 01407 then we only consider localising those attributes 01408 which have a type which is in this set. 01409 01410 01411 Outputs: NewAction: A pointer to the action if it could be allocated. 01412 01413 Returns: AC_FAIL: There was not enough room in the operation history for the 01414 action and the user did not wish to continue. Usually 01415 End() should be called in this situation. 01416 01417 AC_NORECORD: There was not enough room in the operation history for 01418 the action, but the user requested that he wished to 01419 continue without undo. 01420 01421 AC_OK : The action was successfully initialised and added to the 01422 operation. 01423 01424 01425 Purpose: To check that there is sufficient room for the action in the operation 01426 history, and if there is, then to add the action to the operations 01427 action list. 01428 01429 The function calls the Action::Init function passing the runtime class 01430 of a LocaliseCommonAttrAct. 01431 Errors: - 01432 SeeAlso: Action::Init 01433 01434 ********************************************************************************************/ 01435 01436 ActionCode LocaliseCommonAttrAct::Init(Operation* const pOp, 01437 ActionList* pActionList, 01438 NodeRenderableInk* pCompound, 01439 BOOL global, 01440 AttrTypeSet* pAffectedAttrTypes, 01441 Action** NewAction) 01442 01443 { 01444 ActionCode Ac = (Action::Init(pOp, 01445 pActionList, 01446 sizeof(LocaliseCommonAttrAct), 01447 CC_RUNTIME_CLASS(LocaliseCommonAttrAct), 01448 NewAction)); 01449 01450 if (*NewAction != NULL) 01451 { 01452 ((LocaliseCommonAttrAct*)(*NewAction))->CompoundObj = pCompound; 01453 ((LocaliseCommonAttrAct*)(*NewAction))->Global = global; 01454 ((LocaliseCommonAttrAct*)(*NewAction))->pSetOfAffectedAttrTypes = pAffectedAttrTypes; 01455 01456 } 01457 01458 return (Ac); 01459 } 01460 01461 01462 /******************************************************************************************** 01463 01464 > virtual void LocaliseCommonAttrAct::Slaughter() 01465 01466 Author: Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com> 01467 Created: 24/05/95 01468 Inputs: - 01469 Outputs: - 01470 Returns: - 01471 Purpose: destructor which gets called when an operation is deleted 01472 Errors: - 01473 SeeAlso: Action::Slaughter 01474 01475 ********************************************************************************************/ 01476 01477 void LocaliseCommonAttrAct::Slaughter() 01478 { 01479 // Destroy the set of attribute types 01480 if (pSetOfAffectedAttrTypes) 01481 { 01482 pSetOfAffectedAttrTypes->DeleteAll(); 01483 delete pSetOfAffectedAttrTypes; 01484 } 01485 01486 // call the base class to destroy the action 01487 Action::Slaughter(); 01488 }