#include <attrappl.h>
Inheritance diagram for OpRepeatApplyAttribToSelected:
Public Member Functions | |
OpRepeatApplyAttribToSelected () | |
OpRepeatApplyAttribToSelected constructor. | |
void | DoWithParam (OpDescriptor *OpDesc, OpParam *pOpParam) |
Performs the OpApplyAttribToSelected operation. This function applies the NodeAttribute to all selected objects. | |
virtual void | GetOpName (String_256 *OpName) |
The GetOpName fn is overridden so that we return back a description appropriate to the type of attribute that the operation applies. | |
Static Public Member Functions | |
static BOOL | Init () |
OpApplyAttribToSelected initialiser method. | |
static OpState | GetState (String_256 *, OpDescriptor *) |
For finding OpRepeatApplyAttribToSelected state. | |
Static Public Attributes | |
static FillBlobSelectionState | FillBlobState |
Protected Member Functions | |
BOOL | ApplyToSelection (NodeAttribute *Attrib, BOOL Mutate) |
virtual BOOL | DoApply (Node *CurrentNode, NodeAttribute *Attrib, BOOL Mutate, BOOL bEffectRootOnly) |
Definition at line 317 of file attrappl.h.
|
OpRepeatApplyAttribToSelected constructor.
Definition at line 2806 of file attrappl.cpp. 02806 : Operation() 02807 { 02808 }
|
|
Definition at line 3024 of file attrappl.cpp. 03025 { 03026 SelRange* Sel = GetApplication()->FindSelection(); 03027 ERROR3IF(Sel==NULL,"Can't find SelRange!"); 03028 if (Sel==NULL) return FALSE; 03029 Node* FirstSelectedNode = Sel->FindFirst(); 03030 03031 // Find out which spread the selection is on 03032 // Spread* pSpread = FirstSelectedNode->FindParentSpread(); 03033 03034 if (FirstSelectedNode != NULL) // Can't do anything if nothing is selected 03035 { 03036 EffectsStack* pStack = Sel->GetEffectsStack(FALSE, FALSE); // Get cached stack, don't escape derived objects (allow attrs to be applie to derived objects) 03037 ERROR3IF(pStack==NULL, "Failed to get PPStack in ApplyToSelection"); 03038 INT32 stackpos = STACKPOS_TOP; 03039 Range* pLevel = pStack->GetLevelRange(&stackpos, FALSE); // Don't escape old controllers, apply attr to base nodes 03040 Node* pCurrentNode = pLevel->FindFirst(); 03041 03042 // While there are still nodes to apply the attribute to 03043 while (pCurrentNode != NULL) 03044 { 03045 BOOL bEffect = (pCurrentNode->IsAnObject() && ((NodeRenderableInk*)pCurrentNode)->IsValidEffectAttr(Attrib)); 03046 03047 Node* pApplyNode = pCurrentNode; 03048 if (pApplyNode->IsAnObject()) 03049 pApplyNode = ((NodeRenderableInk*)pApplyNode)->GetObjectToApplyTo(Attrib->GetRuntimeClass()); 03050 03051 if (!DoApply(pApplyNode, Attrib, Mutate, bEffect)) 03052 return FALSE; 03053 03054 ContinueSlowJob(); 03055 03056 pCurrentNode = pLevel->FindNext(pCurrentNode); 03057 } 03058 } 03059 03060 return TRUE; 03061 }
|
|
Definition at line 3085 of file attrappl.cpp. 03086 { 03087 ERROR3IF(!CurrentNode->IsBounded(), "DoApply assumes CurrentNode is bounded"); 03088 03089 // have we been allowed to do this ??? 03090 Spread* pSpread = (Spread*)CurrentNode->FindParent(CC_RUNTIME_CLASS(Spread)); 03091 DocRect TempRect = ((NodeRenderableBounded*)CurrentNode)->GetBoundingRect(); 03092 03093 BOOL AttributeExists = FALSE; // Until we find that the attribute does exist 03094 03095 CCRuntimeClass* AttrType = Attrib->GetAttributeType(); 03096 03097 // ----------------------------------------------------------------------------- 03098 // Determine if the current node already has an attribute which is the same 03099 // runtime class as Attrib. 03100 Node* n = CurrentNode->FindFirstChild(); 03101 Node* pLastBoundedNode = NULL; 03102 if (bEffectRootOnly) 03103 { 03104 // BODGE! ------------------------------------------------------------ 03105 // Don't apply stroke transparency as an effect attribute - nothing 03106 // needs it. Test has to be done here because other objects in the 03107 // selection might need it... 03108 if (AttrType==CC_RUNTIME_CLASS(AttrStrokeTransp)) 03109 return TRUE; 03110 // END-BODGE! -------------------------------------------------------- 03111 03112 pLastBoundedNode = CurrentNode->FindLastChild(CC_RUNTIME_CLASS(NodeRenderableBounded)); 03113 ERROR3IF(pLastBoundedNode==NULL, "Attempt to apply effect attr to node with no children"); 03114 03115 if (pLastBoundedNode) n = pLastBoundedNode->FindNext(); 03116 } 03117 03118 while (n != NULL) 03119 { 03120 // Now lets see if we can find an attribute of the same type 03121 // as the one we are interested in. 03122 if (n->IsAnAttribute()) 03123 { 03124 if( ((NodeAttribute*)n)->GetAttributeType() == AttrType) 03125 { 03126 AttributeExists = TRUE; 03127 break; 03128 } 03129 } 03130 n = n->FindNext(); // Find next child of CurrentNode 03131 } 03132 03133 // At this point we have Either ..... 03134 // 1. Found an attribute of the same type as the new one, and we will 03135 // now replace it. 03136 // 2. Found the specific attribute we were looking for and will replace 03137 // that. 03138 // 3. Found an attribute to mutate. 03139 // 4. Found no attribute of the correct type, indicating that it has 03140 // been factored out, and we need to put a new one in here. 03141 03142 // Have we have got an Attribute to do something with ? 03143 NodeAttribute* AttribClone = NULL; 03144 NodeAttribute* pAttr = (NodeAttribute*)n; 03145 if (pAttr) 03146 { 03147 // Yes ! 03148 if (Mutate) 03149 { 03150 // Mutate it into the new type. 03151 AttribClone = ((AttrFillGeometry*)pAttr)->Mutate((AttrFillGeometry*)Attrib); 03152 } 03153 03154 if (AttribClone != NULL) 03155 { 03156 // Set the attribute directly 03157 *((AttrFillGeometry*)pAttr) = *((AttrFillGeometry*)AttribClone); 03158 03159 AttributeManager::pLastNodeAppliedTo = (NodeRenderableInk*)CurrentNode; 03160 03161 delete AttribClone; 03162 AttribClone = NULL; 03163 } 03164 } 03165 else 03166 { 03167 // We've not found an attribute to replace, so we'll have to put 03168 // a new one in 03169 NodeAttribute* TempAttr = NULL; 03170 03171 BOOL FoundAttr = ((NodeRenderableInk*)CurrentNode)-> 03172 FindAppliedAttribute(Attrib->GetAttributeType(), &TempAttr); 03173 03174 if (!FoundAttr || TempAttr == NULL) 03175 return FALSE; 03176 03177 if (Mutate) 03178 { 03179 AttribClone = ((AttrFillGeometry*)TempAttr)->Mutate((AttrFillGeometry*)Attrib); 03180 } 03181 else 03182 { 03183 // We'll just put a copy of our attribute in the tree. 03184 ALLOC_WITH_FAIL(AttribClone ,((NodeAttribute*)Attrib->SimpleCopy()), this) 03185 03186 if (TempAttr->IsAFillAttr()) 03187 { 03188 AttrFillGeometry* NodeReplaced = (AttrFillGeometry*)TempAttr; 03189 03190 // Copy the old fill characteristics into the new Fill 03191 if (!OpApplyAttrib::KeepExistingCharacteristics(NodeReplaced, (AttrFillGeometry*)AttribClone)) 03192 return FALSE; 03193 } 03194 03195 if (Attrib->IsATranspFill() && Attrib->IsAFlatFill()) 03196 { 03197 // If we are mutating into a flat fill, then we need 03198 // to make sure we remove any existing fill blobs. 03199 ((AttrFillGeometry*)TempAttr)->RenderFillBlobs(); 03200 } 03201 } 03202 03203 // If the AttribClone has the same value as an applied attribute 03204 // (A default attr if the attribs have been localised). Then we don't want to apply it ! 03205 if (AttribClone && AttribClone->ShouldBeOptimized() && !bEffectRootOnly) 03206 { 03207 NodeAttribute* pAppliedAttr; 03208 if (((NodeRenderableInk*)CurrentNode)->FindAppliedAttribute(AttribClone->GetAttributeType(), 03209 &pAppliedAttr)) 03210 { 03211 // Do the attributes have the same value ? 03212 if ((IS_SAME_CLASS(AttribClone, pAppliedAttr))) 03213 { 03214 if ((*AttribClone)==(*pAppliedAttr)) 03215 { 03216 AttribClone->CascadeDelete(); // Delete the attribute 03217 03218 // If attribute affect's the bounds of the object (eg. a LineWidth) then invalidate the 03219 // bounds of the object 03220 03221 if (pAppliedAttr->EffectsParentBounds()) 03222 { 03223 ((NodeRenderableBounded*)CurrentNode)->InvalidateBoundingRect(TRUE); 03224 } 03225 03226 delete AttribClone; 03227 AttribClone = NULL; 03228 } 03229 } 03230 } 03231 } 03232 03233 // Effect attributes don't optimise so if the value of this is the 03234 // same as the default value we should not add it here 03235 // 03236 if (AttribClone && bEffectRootOnly && AttribClone->HasEquivalentDefaultValue()) 03237 { 03238 // Just allow the attribute to be hidden 03239 AttribClone->CascadeDelete(); // Delete the attribute 03240 delete AttribClone; 03241 AttribClone = NULL; 03242 } 03243 03244 if (AttribClone) 03245 { 03246 // Finally !! We can add the new attribute node into the tree. 03247 if (bEffectRootOnly) 03248 AttribClone->AttachNode(pLastBoundedNode, NEXT); 03249 else 03250 AttribClone->AttachNode(CurrentNode, FIRSTCHILD); 03251 03252 AttributeManager::pLastNodeAppliedTo = (NodeRenderableInk*)CurrentNode; 03253 03254 // And now it's in the tree, we need to make sure that any fill control 03255 // points are valid. 03256 if (AttribClone->IsAFillAttr()) 03257 { 03258 ((AttrFillGeometry*)AttribClone)->AttributeChanged(); 03259 } 03260 } 03261 } 03262 03263 // Now that the attr value has been set (or left unchanged) test to see if we can remove effect attrs 03264 // Only try to "optimise" effect attributes here if this is going to be a permanent tree change 03265 // Don't bother in the middle of slider dragging 03266 if (pAttr && pAttr->IsEffectAttribute() && bEffectRootOnly) 03267 { 03268 // Effect attributes don't optimise so if the value of this is the 03269 // same as the default value we should remove it here 03270 // 03271 if (pAttr->HasEquivalentDefaultValue()) 03272 { 03273 // "Hide" the node 03274 pAttr->CascadeDelete(); 03275 delete pAttr; 03276 } 03277 } 03278 03279 // Now force a redraw on the attribute 03280 // We release cached data manually, because we need to be clever about effect attributes 03281 // only releasing parent cached data... 03282 // ReleaseCachedForAttrApply((NodeRenderableBounded*)CurrentNode, bEffectRootOnly); // Function not available in this class! 03283 if (bEffectRootOnly) 03284 ((NodeRenderableBounded*)CurrentNode)->ReleaseCached(TRUE, FALSE, FALSE, TRUE); // Parents and Derived data only 03285 else 03286 ((NodeRenderableBounded*)CurrentNode)->ReleaseCached(); // Self, Parents and Children 03287 03288 // (GetSelected... URGH.) 03289 Document::GetSelected()->ForceRedraw(pSpread, TempRect, TRUE, CurrentNode, FALSE); // No automatic call to ReleaseCached 03290 return TRUE; 03291 }
|
|
Performs the OpApplyAttribToSelected operation. This function applies the NodeAttribute to all selected objects.
Reimplemented from Operation. Definition at line 2828 of file attrappl.cpp. 02829 { 02830 ERROR3IF(pOpParam == NULL, "The OpApplyAttribToSelected operation requires an attribute parameter"); 02831 02832 AttrTypeSet AttrTypes; 02833 NodeRenderableInk* pLocalisedCompound = NULL; 02834 NodeRenderableInk* pFactoredOutCompound = NULL; 02835 Node* pCurrent; 02836 02837 Range SelRng(*(GetApplication()->FindSelection())); 02838 02839 BeginSlowJob(); 02840 AttributeManager::pLastNodeAppliedTo = NULL; 02841 02842 // Obtain a pointer to the attribute which we will need to apply to all selected nodes 02843 NodeAttribute* Attrib = (NodeAttribute*)(void *)pOpParam->Param1; 02844 02845 BOOL Mutate = FALSE; 02846 NodeAttribute* OldAttr = NULL; 02847 02848 if (Attrib == NULL) 02849 { 02850 // If the first param is NULL then we are doing a mutation 02851 Attrib = (NodeAttribute*)(void *)pOpParam->Param2; 02852 Mutate = TRUE; 02853 } 02854 else 02855 { 02856 // Someone has specified a Particular Attribute that we should replace 02857 // and ignore all others. 02858 OldAttr = (NodeAttribute*)(void *)pOpParam->Param2; 02859 } 02860 02861 SelRange* Sel; 02862 ObjChangeFlags cFlags; 02863 cFlags.Attribute = TRUE; 02864 ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,NULL); 02865 02866 Sel = GetApplication()->FindSelection(); 02867 if (!Sel->AllowOp(&ObjChange)) 02868 { 02869 FailAndExecute(); 02870 goto EndOperation; 02871 } 02872 02873 // Some Attributes require a second attribute to be changed as well, 02874 // which has to be done within this op. 02875 NodeAttribute* OtherAttrib; 02876 BOOL IsMutate; 02877 OtherAttrib = AttributeManager::GetOtherAttrToApply(Attrib, &IsMutate); 02878 02879 // Before we apply the attribute to the selection we must localise all attributes 02880 // with the same type that we are going to apply. If we don't do this then the 02881 // tree will be left in an invalid state. 02882 02883 AttrTypes.AddToSet((Attrib->GetAttributeType())); 02884 if (OtherAttrib != NULL) 02885 { 02886 AttrTypes.AddToSet((OtherAttrib->GetAttributeType())); 02887 } 02888 02889 // if (!DoLocaliseForAttrChange(&SelRng, &AttrTypes)) 02890 // { 02891 // goto EndOperation; 02892 // } 02893 02894 pCurrent = SelRng.FindFirst(); 02895 02896 // There is no need to localise a compound more than once so we remember the last localised 02897 02898 CCRuntimeClass* AttrType; 02899 Node* pParent; 02900 Node* pObject; 02901 02902 while (pCurrent) 02903 { 02904 pObject = pCurrent; 02905 // Determine if the attribute will get applied to this object, or an alternative object 02906 // (probably its parent) 02907 if (!AttrTypes.IsEmpty()) 02908 { 02909 AttrType = ((AttrTypeItem*)AttrTypes.GetHead())->AttributeType; 02910 ERROR3IF(!AttrType, "AttrType set contains NULL attribute type"); 02911 pObject = ((NodeRenderableInk*)pObject)->GetObjectToApplyTo(AttrType); 02912 } 02913 02914 { 02915 // We only need to localise those nodes which have a compound parent 02916 pParent = pObject->FindParent(); 02917 ERROR3IF(pParent == NULL, "Range::DoLocaliseForAttrChange, node found without a parent"); 02918 02919 // Only localise the parent if it is a compound node which has not already been localised 02920 if ((pParent->IsCompound()) && (pParent != pLocalisedCompound)) 02921 { 02922 ((NodeRenderableInk*)pParent)->LocaliseCommonAttributes(FALSE, // No need to check for duplicates 02923 TRUE, // Localise globally 02924 &AttrTypes);// Only attributes of these types 02925 02926 pLocalisedCompound = (NodeRenderableInk*)pParent; // Remember that it's been localised 02927 } 02928 } 02929 02930 pCurrent = SelRng.FindNext(pCurrent); 02931 } 02932 02933 ApplyToSelection(Attrib, Mutate); 02934 02935 if (OtherAttrib != NULL) 02936 { 02937 ApplyToSelection(OtherAttrib, IsMutate); 02938 delete OtherAttrib; 02939 } 02940 02941 // Having applied the attributes, we must now try and factor out the newly 02942 // applied attributes 02943 // if (!DoFactorOutAfterAttrChange(&SelRng, 02944 // &AttrTypes)) 02945 // { 02946 // goto EndOperation; 02947 // } 02948 02949 // Scan the range 02950 pCurrent = SelRng.FindFirst(); 02951 02952 // There is no need to factor out the attributes on a compound more than once, so we 02953 // remember the last compound node which has had its attributes factored out 02954 02955 while (pCurrent) 02956 { 02957 // If the object can discard its attribute children then we should not try to factor 02958 // out its attributes 02959 CCRuntimeClass* AttrType; 02960 02961 pObject = pCurrent; 02962 if (!AttrTypes.IsEmpty()) 02963 { 02964 AttrType = ((AttrTypeItem*)AttrTypes.GetHead())->AttributeType; 02965 ERROR3IF(!AttrType, "AttrType set contains NULL attribute type"); 02966 pObject = ((NodeRenderableInk*)pObject)->GetObjectToApplyTo(AttrType); 02967 } 02968 02969 { 02970 // We only need to factor out attributes on nodes which have a compound parent 02971 pParent = pObject->FindParent(); 02972 ERROR3IF(pParent == NULL, "Range::DoFactorOutAfterAttrChange, node found without a parent"); 02973 02974 // Only factor out attribs if the parent has not already had its attribs factored out 02975 if ((pParent->IsCompound()) && (pParent != pFactoredOutCompound)) 02976 { 02977 ((NodeRenderableInk*)pParent)->FactorOutCommonChildAttributes(TRUE, &AttrTypes); 02978 02979 pFactoredOutCompound = (NodeRenderableInk*)pParent; // Remember that it's been localised 02980 } 02981 } 02982 02983 pCurrent = SelRng.FindNext(pCurrent); 02984 } 02985 02986 AttrFillGeometry::LastRenderedMesh = NULL; 02987 02988 if (Document::GetSelected()) 02989 Document::GetSelected()->SetModified(TRUE); 02990 02991 ObjChange.Define(OBJCHANGE_FINISHED,cFlags,NULL,NULL); 02992 if (!UpdateChangedNodes(&ObjChange)) 02993 FailAndExecute(); 02994 02995 AttributeManager::LastAppliedBounds = Sel->GetBoundingRect(); 02996 02997 EndOperation: 02998 AttrTypes.DeleteAll(); 02999 03000 EndSlowJob(); 03001 End(); // End of operation 03002 }
|
|
The GetOpName fn is overridden so that we return back a description appropriate to the type of attribute that the operation applies.
Reimplemented from Operation. Definition at line 3372 of file attrappl.cpp.
|
|
For finding OpRepeatApplyAttribToSelected state.
Definition at line 3341 of file attrappl.cpp. 03342 { 03343 OpState OpSt; 03344 03345 SelRange* Sel = GetApplication()->FindSelection(); 03346 ERROR2IF(Sel==NULL,OpSt,"Can't find SelRange!"); 03347 03348 // The Operation is greyed if there are no nodes selected 03349 OpSt.Greyed = ( (Sel->FindFirst() == NULL) ); 03350 03351 return(OpSt); 03352 }
|
|
OpApplyAttribToSelected initialiser method.
Reimplemented from SimpleCCObject. Definition at line 3312 of file attrappl.cpp. 03313 { 03314 // Register the opdescriptors for the OpApplyAttribToSelected operation 03315 OpDescriptor* OpDesc = new OpDescriptor( 03316 0, 03317 _R(IDS_APPLYATTRIBOP), 03318 CC_RUNTIME_CLASS(OpRepeatApplyAttribToSelected), 03319 OPTOKEN_REPEATAPPLYATTRIB, 03320 OpRepeatApplyAttribToSelected::GetState); 03321 03322 ERRORIF(!OpDesc, _R(IDE_NOMORE_MEMORY), FALSE); 03323 return(OpDesc != NULL); 03324 }
|
|
Definition at line 331 of file attrappl.h. |