#include <attrmgr.h>
Inheritance diagram for AttributeManager:

Public Types | |
| enum | AttrsToMakeCurrent { ALL, NOT_APPLIED, NONE } |
Public Member Functions | |
| AttributeManager () | |
| ~AttributeManager () | |
| Attribute manager destructor Currently destroys all attributes in all attribute groups. | |
| BOOL | InitInstance () |
| Creates the current attribute groups, and adds the initial current attributes to them. | |
| AttrsToMakeCurrent | GetAttributesToMakeCurrent (List &Attribs, List &AttrGroupsList, BOOL bPasteAttrs) |
| To determine which attributes in the Attribs list to make current. The user is prompted where neccessary. | |
| BOOL | WeShouldMakeAttrCurrent (BOOL AttributeApplied, NodeAttribute *pAttr, List *pAttrGroupList, BOOL DroppedAttr=FALSE, BOOL AttrDroppedOntoPage=FALSE) |
| To determine if we should make an attribute current or not. The routine does NOT delete the Attrib if it is not being made current. | |
| BOOL | ApplyCurrentAttribsToNode (NodeRenderableInk *Node) |
| This function determines the attribute group associated with the object and then applies all attributes in the group to the object. If the group has a base group then all attributes in the base group with types different to those already applied get added to the object etc. | |
| NodeAttribute * | GetSelToolCurrentAttribute (CCRuntimeClass *AttrType) |
| For finding current attribute pAttrType in the current attribute group specified by the currently selected tool. | |
| NodeAttribute * | GetCurrentAttribute (CCRuntimeClass *AttrGroup, CCRuntimeClass *AttrType) |
| For finding current attribute pAttrType in attribute group pAttrGroup. | |
| void | GetCurrentLineAndFillColour (CCRuntimeClass *AttrGroup, DocColour *LineCol, DocColour *FillCol) |
| BOOL | WriteCurrentAttributes (BaseCamelotFilter *pFilter) |
| void | UpdateForDeletedColours (ColourList *ParentList) |
| Called by the ColourManager when colours in use by the attribute manager may have been deleted. | |
Static Public Member Functions | |
| static BOOL | InitDefaults () |
| Initialises the Attribute Manager. Registers basic attributes Declares attribute preferences When TRUE - Whenever an attribute is applied to objects the attribute becomes a current attribute. When TRUE - The user is prompted before setting a current attribute, except when the LastAttrAppliedBecomesCurrent preference is TRUE when it makes no sense to prompt the user. | |
| static void | Deinit () |
| static void | AttributeSelected (NodeAttribute *Attrib, NodeAttribute *OldAttr=NULL) |
| This function should be called whenever an attribute is selected by the user. | |
| static void | AttributesSelected (List &AttribsToApply, UINT32 OpName) |
| This high level function should be called whenever we need to apply multiple attributes to the selection (eg. PasteAttributes). | |
| static void | ApplyAttribToNode (NodeRenderableInk *InkNode, NodeAttribute *NewAttr) |
| Replaces an attribute within a specified Ink Node. | |
| static void | ReplaceAttributes (NodeAttribute *Attrib, List *OldAttrs) |
| static void | UpdateCurrentAttr (NodeAttribute *Attr, BOOL Mutate, List *pAttrGroupList, BOOL TellWorld=TRUE) |
| Adds Attr to all attribute groups in the AttrGroupList. If the list is empty then the attribute gets added to the attribute group associated with the selected tool. | |
| static BOOL | UpdateCurrentAppliedAttr (NodeAttribute *pAttr, List *pAttrGroupList, BOOL bAttrApplied, BOOL bMutate) |
| static BOOL | UpdateAfterAttrApplied (NodeAttribute *pAttr) |
| static BOOL | CanBeAppliedToSelection (NodeAttribute *Attrib, List *pAttrGroups) |
| This function would ideally live in the SelRange. It determines if the attribute can be applied to at least one object in the selection. | |
| static BOOL | CanBeAppliedToNode (NodeRenderableInk *pObject, NodeAttribute *Attrib, List *pAttrGroups) |
| This function would ideally live in the SelRange. It determines if the attribute can be applied to a specified object. | |
| static void | FindDefaultColour (ColourList *ColList, UINT32 NameResID, DocColour *Result) |
| static UINT32 | RegisterDefaultAttribute (CCRuntimeClass *pNodeType, AttributeValue *pValue) |
| static AttributeEntry * | GetDefaultAttributes () |
| Get a copy of all the default attributes. This is used by render regions and import filters to initialise themselves to a sensible default state. | |
| static NodeAttribute * | GetDefaultAttribute (AttrIndex AttrID) |
| static AttributeValue * | GetDefaultAttributeVal (AttrIndex AttrID) |
| static BOOL | GetDefaultAttribute (AttrIndex aiToGet, AttributeValue *pavReturn) |
| Gets the default value of a particular attribute. | |
| static UINT32 | GetNumAttributes () |
| Find out how many attributes have been registered with the attribute manager. This also tells you how long the default attribute array is as returned by AttributeManager::GetDefaultAttributes. | |
| static BOOL | ApplyBasedOnDefaults (Node *Target, AttributeEntry *AttrsToApply) |
| Given a set of attributes, apply the ones that differ from the defaults to the specified node. Most commonly used by import filters. | |
| static NodeAttribute * | GetOtherAttrToApply (NodeAttribute *AttrApplied, BOOL *IsMutate) |
Static Public Attributes | |
| static BOOL | LastAttrAppliedBecomesCurrent = 1 |
| static BOOL | AskBeforeSettingCurrentAttr = 0 |
| static BOOL | ShouldAskAboutContoneColours = 1 |
| static BOOL | HaveAskedAboutContoneColours = 0 |
| static BOOL | UserCancelledContoneColours = 0 |
| static BOOL | SendMessages = 1 |
| static DocColour | DefaultBlack = DocColour(0L, 0L, 0L) |
| static DocColour | DefaultWhite = DocColour(255L, 255L, 255L) |
| static NodeRenderableInk * | pLastNodeAppliedTo = NULL |
| static DocRect | LastAppliedBounds = DocRect(0,0,0,0) |
Private Member Functions | |
| BOOL | CreateCurrentAttributeGroup (CCRuntimeClass *AttrGroup, CCRuntimeClass *BaseGroup, String_256 &GrpName) |
| This fn creates a new AttributeGroup. An AttributeGroup will contain a set of current attributes which get applied to new objects which are associated with the group. | |
| NodeAttribute * | UpdateCurrentAttribute (CCRuntimeClass *AttrGroup, NodeAttribute *Attribute, BOOL fCheckTransparency=TRUE, BOOL DefiningGroups=FALSE, BOOL TellWorld=TRUE, BOOL bForceNewValue=FALSE) |
| This function Adds Attribute to the specified AttrGroup. | |
| AttributeGroup * | GetAttributeGroup (CCRuntimeClass *GroupID) |
| This function obtains a pointer to the requested group. | |
| void | AddAttributeToGroup (AttributeGroup *pAttrGroup, NodeAttribute *Attribute, BOOL fCheckTransparency, BOOL TellWorld=TRUE, BOOL bRetainValues=FALSE) |
| This function is a helper for AttributeManager::UpdateCurrentAttribute. it adds the specified attribute to the specified Attribute group. and BROADCASTS a CurrentAttrChangedMsg message. | |
| BOOL | WriteCurrentAttributeGroupRecord (BaseCamelotFilter *pFilter, AttributeGroup *pGroup) |
Static Private Member Functions | |
| static void | ApplyAttribToNodeHelper (NodeRenderableInk *InkNode, NodeAttribute *NewAttr) |
| Replaces an attribute within a specified Ink Node. | |
| static BOOL | RegisterBasicAttributes () |
| Register all the 'built-in' rendering attributes that Camelot has. This allows us to register these basic attributes first and in a known order, so we can use a constant instead of a variable to access them, thus allowing us to get to these attributes quicker. | |
| static BOOL | EnsureTableSpaceAvailable () |
Private Attributes | |
| List | AttrGroupList |
Static Private Attributes | |
| static AttributeEntry * | DefaultAttrValues = NULL |
| static NodeTypeEntry * | DefaultNodeAttrs = NULL |
| static UINT32 | NumAttributes = 0 |
| static UINT32 | AttributeTableSize = 0 |
Friends | |
| class | BaseCamelotFilter |
It has been extended to store default attribute information by Tim
Definition at line 215 of file attrmgr.h.
|
|
Definition at line 255 of file attrmgr.h. 00255 { ALL, NOT_APPLIED, NONE };
|
|
|
Definition at line 199 of file attrmgr.cpp.
|
|
|
Attribute manager destructor Currently destroys all attributes in all attribute groups.
Definition at line 1069 of file attrmgr.cpp. 01070 { 01071 // Delete all groups 01072 AttributeGroup* CurrentGroup = (AttributeGroup*)AttrGroupList.GetHead(); 01073 NodeAttribute* CurrentAttr; 01074 NodeAttribute* NextAttr; 01075 while (CurrentGroup != NULL) 01076 { 01077 // Delete all attributes in the group 01078 CurrentAttr = CurrentGroup->AttrListHd;// get pointer to first attribute in the 01079 // group 01080 while (CurrentAttr != NULL) 01081 { 01082 NextAttr = (NodeAttribute*)CurrentAttr->FindNext(); 01083 delete CurrentAttr; 01084 CurrentAttr = NextAttr; 01085 } 01086 01087 delete (AttrGroupList.RemoveItem((ListItem*)CurrentGroup)); 01088 CurrentGroup =(AttributeGroup*)AttrGroupList.GetHead(); // Get next group 01089 } 01090 }
|
|
||||||||||||||||||||||||
|
This function is a helper for AttributeManager::UpdateCurrentAttribute. it adds the specified attribute to the specified Attribute group. and BROADCASTS a CurrentAttrChangedMsg message.
TellWorld: Broadcast a CurrentAttrChangedMsg
Definition at line 1543 of file attrmgr.cpp. 01548 { 01549 // Add Attribute to the group 01550 if (pAttrGroup->AttrListHd != NULL) 01551 Attribute->AttachNode(pAttrGroup->AttrListHd, NEXT, fCheckTransparency); 01552 else 01553 pAttrGroup->AttrListHd = Attribute; 01554 01555 // If this is a Fill Attribute then we need to make sure its 01556 // in a sensible state. 01557 if (Attribute->IsAFillAttr()) 01558 { 01559 AttrFillGeometry* Fill = (AttrFillGeometry*)Attribute; 01560 // Ensure that all it's control points are deselected, else 01561 // when it is applied to an object, the user may get confused. 01562 Fill->DeselectAll(); 01563 01564 if (!bRetainValues && Fill->GetBoundingRect().IsEmpty()) 01565 { 01566 // If the bounding box is Empty then we know that this 01567 // fill has never been applied to an object before. 01568 // We ensure that it's control points are Null, so 01569 // they will be set to some sensible default (centre of 01570 // the object usually) when eventually applied. 01571 DocCoord coord; 01572 Fill->SetStartPoint( &coord ); 01573 Fill->SetEndPoint( &coord ); 01574 Fill->SetEndPoint2( &coord ); 01575 } 01576 01577 } 01578 01579 // Tell everyone that the Current Attributes have Changed. 01580 if (TellWorld) 01581 { 01582 BROADCAST_TO_ALL(CurrentAttrChangedMsg()); 01583 } 01584 }
|
|
||||||||||||
|
Replaces an attribute within a specified Ink Node.
Definition at line 3398 of file attrmgr.cpp. 03399 { 03400 // need to check the case where the selected node 03401 03402 ApplyAttribToNodeHelper(InkNode, NewAttr); 03403 03404 // We only need to tell everyone if the node is within the selection 03405 if (InkNode != NULL && (InkNode->IsSelected() || InkNode->IsChildOfSelected()) && SendMessages) 03406 { 03407 // Inform the selection that attributes have changed 03408 SelRange* Sel = GetApplication()->FindSelection(); 03409 if (Sel) 03410 Sel->AttrsHaveChanged(); 03411 03412 if (NewAttr->IsKindOf(CC_RUNTIME_CLASS(AttrColourChange)) ) 03413 { 03414 // If the Attrib was a Colour Mutator, then we must have changed a colour 03415 // so lets tell someone about it 03416 BROADCAST_TO_ALL(SelChangingMsg(SelChangingMsg::COLOURATTCHANGED)); 03417 } 03418 else 03419 { 03420 // We've probably changed a Colour 03421 BROADCAST_TO_ALL(SelChangingMsg(SelChangingMsg::COLOURATTCHANGED)); 03422 // and the Attrib may have changed shape or summit. Who knows ? 03423 BROADCAST_TO_ALL(SelChangingMsg(SelChangingMsg::NONCOLOURATTCHANGED)); 03424 03425 if (Sel) Sel->UpdateBounds(); 03426 } 03427 03428 // And ensure that if we've caused the SelRange to set up any delayed message 03429 // broadcasts, that it sends them now rather than at some random time in the future 03430 // when some Op just happens to end. 03431 if (Sel) 03432 Sel->BroadcastAnyPendingMessages(); 03433 } 03434 03435 03436 delete NewAttr; 03437 }
|
|
||||||||||||
|
Replaces an attribute within a specified Ink Node.
Scope: private
Definition at line 3458 of file attrmgr.cpp. 03459 { 03460 #if !defined(EXCLUDE_FROM_RALPH) 03461 BOOL ApplyAttribute = FALSE; 03462 List AttrGroupList; 03463 03464 pLastNodeAppliedTo = NULL; 03465 03466 if (InkNode != NULL && NewAttr != NULL) 03467 { 03468 ApplyAttribute = CanBeAppliedToNode(InkNode, NewAttr, &AttrGroupList); 03469 } 03470 03471 if (ApplyAttribute) 03472 { 03473 // Obtain a pointer to the op descriptor for the attribute operation 03474 OpDescriptor* OpDesc = OpDescriptor::FindOpDescriptor(CC_RUNTIME_CLASS(OpApplyAttribToNode)); 03475 03476 // Get the number of selected fill control points, 'cus we may want to do 03477 // something different depending on how many their are. 03478 03479 #ifdef BUILDSHADOWS 03480 // New check which will only be done in BUILDSHADOWS 03481 if(InkNode->IS_KIND_OF(NodeShadow)) 03482 { 03483 AttrFillGeometry::SelectionCount = 1; 03484 } 03485 else 03486 #endif 03487 { 03488 AttrFillGeometry::SelectionCount = AttrFillGeometry::CountSelectionControlPoints(); 03489 } 03490 03491 // Removed the following section as we can do this now 03492 /* if (IS_A(NewAttr, AttrColourDrop)) 03493 { 03494 if (IS_A (InkNode, NodeBitmap)) 03495 { 03496 // Ask the user wether or not they want to use a 24bit copy of the BMP or use the Default Bitmap? 03497 //InformWarning(_R(IDS_BFX_BMP_CONVERT_MSG),_R(IDS_OK),0,0,0,1,2); 03498 03499 NodeBitmap* pBitmap = (NodeBitmap*) InkNode; 03500 03501 if (pBitmap->GetBitmap ()->ActualBitmap->GetBitmapInfoHeader ()->biBitCount == 32) 03502 { 03503 // we don't want the code to fire if were trying to apply a nocolour attribute .... 03504 03505 BOOL isNoColour = FALSE; 03506 03507 isNoColour = (((FlatFillAttribute*) NewAttr->GetAttributeValue ())->GetStartColour ()->IsTransparent ()); 03508 03509 if (!isNoColour) 03510 { 03511 // Load and build the question text. 03512 String_256 QueryString(_R(IDS_QUERYTRANSP322)); 03513 03514 // The only way of bringing up a box with a string in it 03515 Error::SetError(0, QueryString, 0); 03516 INT32 DlgResult = InformMessage(NULL, _R(IDS_YES), _R(IDS_NO)); 03517 Error::ClearError(); 03518 03519 switch (DlgResult) 03520 { 03521 case 2: // NO 03522 return; // break out of this stuff! 03523 } 03524 } 03525 } 03526 } 03527 } 03528 */ 03529 // Invoke the operation, passing Attrib as a parameter 03530 OpParam tempParam((void *)InkNode,(void *)NewAttr); 03531 OpDesc->Invoke(&tempParam); 03532 } 03533 03534 Document* CurrentDoc = Document::GetSelected(); 03535 if (CurrentDoc == NULL) 03536 return; // We are not going to be able to do anything if there is no document 03537 03538 AttributeManager& AttrMgr = CurrentDoc->GetAttributeMgr(); 03539 03540 if (AttrMgr.WeShouldMakeAttrCurrent(ApplyAttribute, NewAttr, &AttrGroupList, 03541 TRUE, // Drag n' drop 03542 InkNode == NULL)) // Dropped onto page 03543 { 03544 UpdateCurrentAttr(NewAttr, NewAttr->IsAFillAttr(), &AttrGroupList); 03545 03546 // Some Attributes require a second attribute to be changed as well. 03547 BOOL IsMutate; 03548 NodeAttribute* pOther = AttributeManager::GetOtherAttrToApply(NewAttr, &IsMutate); 03549 03550 if (pOther != NULL) 03551 { 03552 UpdateCurrentAttr(pOther, IsMutate, &AttrGroupList); // can't have a NULL AttrGroupList 03553 // or it will apply to tools list 03554 } 03555 03556 if (pOther) 03557 { 03558 delete pOther; 03559 } 03560 } 03561 03562 // Don't forget the AttrGroupList 03563 AttrGroupList.DeleteAll(); 03564 #endif 03565 }
|
|
||||||||||||
|
Given a set of attributes, apply the ones that differ from the defaults to the specified node. Most commonly used by import filters.
Definition at line 2287 of file attrmgr.cpp. 02288 { 02289 // Cycle through each type of attribute, and add it if: 02290 // (a) It is of a type that can take the attribute, and 02291 // (b) the attribute is different to the default attribute. 02292 02293 // There is a short cut for telling if the attribute has been changed from the default; 02294 // if the pointer to the attribute is still the same as our copy, then it can't have 02295 // changed 02296 02297 // ****** Bodge ******** 02298 // We must make the Line and Fill colours in the Default Attrs 02299 // into Index colours in the Current Document !! 02300 /* 02301 DocColour DefBlack; 02302 FindDefaultColour(ColourManager::GetCurrentColourList(), 02303 _R(IDS_BLACKNAME), &DefBlack); 02304 02305 ((StrokeColourAttribute*)DefaultAttrValues[ATTR_STROKECOLOUR].pAttr)->SetStartColour(&DefBlack); 02306 ((FillGeometryAttribute*)DefaultAttrValues[ATTR_FILLGEOMETRY].pAttr)->SetStartColour(&DefBlack); 02307 */ 02308 // ****** End Bodge ******** 02309 02310 for (INT32 i = NumAttributes - 1; i >= 0; i--) 02311 { 02312 // Has it changed, and is it of the right node type? 02313 if (!AttrsToApply[i].Ignore && 02314 (DefaultAttrValues[i].pAttr != AttrsToApply[i].pAttr) && 02315 (Target->IsKindOf(DefaultNodeAttrs[i].pNodeType))) 02316 { 02317 // This node can take this type of attribute. 02318 if ((DefaultAttrValues[i].pAttr == NULL) || 02319 (AttrsToApply[i].pAttr->GetRuntimeClass() != 02320 DefaultAttrValues[i].pAttr->GetRuntimeClass()) || 02321 AttrsToApply[i].pAttr->IsDifferent(DefaultAttrValues[i].pAttr)) 02322 { 02323 // The attribute is different to the default - construct the appropriate 02324 // attribute node. 02325 Node *pNode = AttrsToApply[i].pAttr->MakeNode(); 02326 02327 // Enough memory? 02328 if (pNode == NULL) 02329 return FALSE; 02330 02331 // Add it to the target 02332 pNode->AttachNode(Target, FIRSTCHILD); 02333 } 02334 } 02335 02336 } 02337 02338 // All default attributes processed ok. 02339 return TRUE; 02340 }
|
|
|
This function determines the attribute group associated with the object and then applies all attributes in the group to the object. If the group has a base group then all attributes in the base group with types different to those already applied get added to the object etc.
Definition at line 1740 of file attrmgr.cpp. 01741 { 01742 ERROR3IF(Node == NULL, "NULL object passed to AttributeManager::ApplyCurrentAttribsToNode"); 01743 01744 // Find the attribute group that contains the attributes we need to initially apply to the 01745 // node. 01746 CCRuntimeClass* IDCurrentAttrGroup = Node->GetCurrentAttribGroup(); 01747 ERROR3IF (IDCurrentAttrGroup == NULL, "Object has NULL attribute group associated with it"); 01748 01749 // We need to find out quickly if an attribute has already been applied to Node 01750 // Maps Attribute types to TRUE/FALSE values 01751 CCAttrMap* pAppliedAttrsMap; 01752 01753 try 01754 { 01755 pAppliedAttrsMap = new CCAttrMap(30); 01756 } 01757 catch( ... ) 01758 { 01759 return FALSE; 01760 } 01761 01762 // Loop back here to apply base group attributes 01763 do 01764 { 01765 // Search for IDCurrentAttrGroup 01766 AttributeGroup* CurrentGrp = (AttributeGroup*)AttrGroupList.GetHead(); 01767 while (CurrentGrp != NULL) 01768 { 01769 if (CurrentGrp->AttrGroup == IDCurrentAttrGroup) // Found the group 01770 { 01771 // Create a copy of each attribute and add it as a child of Node 01772 NodeAttribute* CurrentAttrib = CurrentGrp->AttrListHd; 01773 while (CurrentAttrib != NULL) 01774 { 01775 // Has an attribute of the same type already been applied to the node, 01776 // this should only ever be the case if we are applying attributes from a base group !. 01777 CCRuntimeClass* CurrentAttrType = CurrentAttrib->GetAttributeType(); 01778 01779 void* NotUsed; 01780 if( !pAppliedAttrsMap->Lookup( CurrentAttrType, NotUsed ) && 01781 Node->RequiresAttrib( CurrentAttrib ) ) 01782 { 01783 // Ensure the nodes bounding box is up to date, so that fill 01784 // attributes can be scaled correctly. 01785 Node->InvalidateBoundingRect(); 01786 DocRect NodeBounds = Node->GetBoundingRect(TRUE); 01787 01788 // Take a copy of the attribute 01789 NodeAttribute* AttribClone = (NodeAttribute*)CurrentAttrib->SimpleCopy(); 01790 ERRORIF(!AttribClone, _R(IDE_NOMORE_MEMORY), FALSE); 01791 01792 // Scale and move the attributes bounds so that it is ready to apply to the 01793 // new object. 01794 AttribClone->TransformToNewBounds(NodeBounds); 01795 01796 // Attach AttribClone to Node 01797 AttribClone->AttachNode(Node, FIRSTCHILD); 01798 01799 if (AttribClone->GetAttributeType() == CC_RUNTIME_CLASS(AttrFillGeometry) || 01800 AttribClone->GetAttributeType() == CC_RUNTIME_CLASS(AttrTranspFillGeometry)) 01801 { 01802 // Now the Attribute is in the tree, we need to tell the fill 01803 // attribute to check that it's control points are valid. 01804 // Unless the fill we transformed above, this will usually 01805 // involve the fill 'centring' itself within the bounds of its 01806 // parent. 01807 ((AttrFillGeometry*)AttribClone)->AttributeChanged(); 01808 } // end if 01809 01810 // Add the attributes type to the applied attributes map so that it does not get 01811 // applied again. 01812 pAppliedAttrsMap->SetAt(CurrentAttrType, NULL); 01813 } 01814 CurrentAttrib = (NodeAttribute*)CurrentAttrib->FindNext(); 01815 } 01816 // ok now apply attributes from the base group, if one exists 01817 IDCurrentAttrGroup = CurrentGrp->BaseGroup; 01818 break; 01819 } 01820 CurrentGrp = (AttributeGroup *) AttrGroupList.GetNext(CurrentGrp); 01821 ERROR3IF(CurrentGrp == NULL, "Unable to find attribute group"); 01822 } 01823 // break takes us here 01824 } while (IDCurrentAttrGroup != NULL); 01825 01826 delete pAppliedAttrsMap; // Map no longer required 01827 return TRUE; 01828 }
|
|
||||||||||||
|
This function should be called whenever an attribute is selected by the user.
OldAttr: When no-null, this specifies the node which 'Attrib' is to replace. It is used when an attribute is edited. When Attrib == NULL, this specifies a Mutator (see above). Intermediate: TRUE when we expect someone to call AttributeSelected again after this call with the same attr types, same selection and Intermediate set to FALSE If any nodes are selected the function invokes an operation to apply the attribute to the selected nodes. If no nodes are selected then the attribute may become a current attribute depending on the preferences.
Definition at line 2389 of file attrmgr.cpp. 02390 { 02391 #if !defined(EXCLUDE_FROM_RALPH) 02392 ENSURE( (Attrib != NULL || OldAttr != NULL), "NULL attributes passed to AttributeSelected"); 02393 02394 BOOL Mutate = (Attrib == NULL); 02395 AttrFillGeometry* Mutator = NULL; 02396 02397 pLastNodeAppliedTo = NULL; 02398 02399 // If parameter one is NULL then we must be doing a Mutation 02400 if (Mutate) 02401 { 02402 ERROR3IF(!OldAttr->IsAFillAttr(), "A Mutator must be a fill attribute"); 02403 // Make a more sensible pointer 02404 Mutator = (AttrFillGeometry*)OldAttr; 02405 } 02406 02407 // If there are any objects selected then the attribute needs to be applied to these objects 02408 // OpDescriptor* OpDesc = NULL; 02409 // BOOL MakeAttrCurrent = FALSE; // until we know better 02410 02411 SelRange* Sel = GetApplication()->FindSelection(); 02412 ERROR3IF(Sel==NULL,"Can't find SelRange!"); 02413 if (Sel==NULL) return; 02414 02415 // If there are no objects in the selection, or if none of the selected objects require 02416 // the attribute, then it will not be applied 02417 02418 BOOL ApplyAttribute; 02419 02420 List AttrGroupList; 02421 02422 if (Attrib != NULL) 02423 { 02424 ApplyAttribute = CanBeAppliedToSelection(Attrib, &AttrGroupList); 02425 } 02426 else 02427 { 02428 ERROR3IF(OldAttr == NULL, "What are we applying then exactly ??"); 02429 ApplyAttribute = CanBeAppliedToSelection(OldAttr, &AttrGroupList); // Mutator 02430 } 02431 02432 02433 if (ApplyAttribute) 02434 { 02435 // We need to invoke an operation to apply the attribute to the currently selected 02436 // objects. 02437 02438 // Get the number of selected fill control points, 'cus we may want to do 02439 // something different depending on how many their are. 02440 AttrFillGeometry::SelectionCount = AttrFillGeometry::CountSelectionControlPoints(); 02441 02442 // Obtain a pointer to the op descriptor for the attribute operation 02443 BOOL bApplying = TRUE; 02444 OpDescriptor* OpDesc = OpDescriptor::FindOpDescriptor(CC_RUNTIME_CLASS(OpApplyAttribToSelected)); 02445 02446 // But first ... Was the pervious Op the same ? 02447 Operation* pLastOp = Document::GetSelected()->GetOpHistory().FindLastOp(); 02448 02449 if (Mutate && pLastOp && pLastOp->GetRuntimeClass() == CC_RUNTIME_CLASS(OpApplyAttribToSelected)) 02450 { 02451 // The last operation was similar to this one, but was it exactly the same type ? 02452 OpApplyAttribToSelected* pLastApplyOp = (OpApplyAttribToSelected*)pLastOp; 02453 02454 if (pLastApplyOp->GetValueChangeType() == Mutator->GetRuntimeClass() && 02455 pLastApplyOp->IsMergeableApplyOp()) 02456 { 02457 // Yep, they are exactly the same type of value change. 02458 // So we don't need to do an undoable op for this new change, 02459 // we can just invoke a special op that will change the attributes 02460 // directly. 02461 02462 // But first ... Is the selection still the same ? 02463 RestoreSelectionsAction* pRestoreSelAct = (RestoreSelectionsAction*) 02464 pLastApplyOp->GetUndoActionList()->FindActionOfClass(CC_RUNTIME_CLASS(RestoreSelectionsAction)); 02465 SelectionState* LastOpsSelection = pRestoreSelAct->GetSelState(); 02466 02467 SelectionState CurrentSelection; 02468 CurrentSelection.Record(); 02469 02470 if (*LastOpsSelection == CurrentSelection) 02471 { 02472 FillBlobSelectionState CurrentFillBlobState; 02473 CurrentFillBlobState.Record(); 02474 02475 if (OpRepeatApplyAttribToSelected::FillBlobState == CurrentFillBlobState) 02476 { 02477 OpDesc = OpDescriptor::FindOpDescriptor(CC_RUNTIME_CLASS(OpRepeatApplyAttribToSelected)); 02478 bApplying = FALSE; 02479 } 02480 } 02481 } 02482 } 02483 02484 // Invoke the operation, passing Attrib as a parameter 02485 OpParam tempParam((void *)Attrib,(void *)OldAttr); 02486 OpDesc->Invoke(&tempParam); 02487 02488 // Remember the current blob selection state, so we can decide whether or not to 02489 // merge future apply operations 02490 if (bApplying) 02491 OpRepeatApplyAttribToSelected::FillBlobState.Record(); 02492 02493 UpdateAfterAttrApplied(Mutate ? Mutator : NULL); 02494 02495 } 02496 02497 BOOL bCurrentUpdated = UpdateCurrentAppliedAttr(Mutate ? Mutator: Attrib, &AttrGroupList, ApplyAttribute, Mutate); 02498 if (!bCurrentUpdated) 02499 { 02500 // Allow fill tools to update after a cancel 02501 BROADCAST_TO_ALL(SelChangingMsg(SelChangingMsg::NONCOLOURATTCHANGED)); 02502 } 02503 02504 // Tidy up attributes because they were only patterns and are no longer needed 02505 if (Mutate) 02506 { 02507 if (Mutator != NULL) 02508 { 02509 delete Mutator; 02510 Mutator = NULL; 02511 } 02512 } 02513 if (Attrib != NULL) 02514 { 02515 delete Attrib; 02516 Attrib = NULL; 02517 } 02518 02519 // Don't forget the AttrGroupList 02520 AttrGroupList.DeleteAll(); 02521 02522 // And ensure that if we've caused the SelRange to set up any delayed message 02523 // broadcasts, that it sends them now rather than at some random time in the future 02524 // when some Op just happens to end. 02525 Sel->BroadcastAnyPendingMessages(); 02526 #endif 02527 }
|
|
||||||||||||
|
This high level function should be called whenever we need to apply multiple attributes to the selection (eg. PasteAttributes).
very important ~~~~~~~~~~~~~~ This function only ever applies copies of attributes in the AttribsToApply list. It is the responsibility of the caller to delete these attributes, if this is appropriate. OpName: The name to give the operation which is performed by this function to apply attributes. eg. 'Paste Attributes'
If no nodes are selected then the attributes may become current depending on the preferences and what the user decides.
Definition at line 2634 of file attrmgr.cpp. 02635 { 02636 #if !defined(EXCLUDE_FROM_RALPH) 02637 // The AttributeList cannot be empty 02638 ERROR3IF(AttribsToApply.IsEmpty(), "No attributes to apply in AttributeManager::AttributesSelected"); 02639 if (AttribsToApply.IsEmpty()) return; // nothing to do 02640 02641 // If there is no current document then there is very little we can do 02642 Document* CurrentDoc = Document::GetSelected(); 02643 if (CurrentDoc == NULL) 02644 return; // We are not going to be able to do anything if there is no document 02645 02646 SelRange* Sel = GetApplication()->FindSelection(); 02647 ERROR3IF(Sel==NULL,"Can't find SelRange!"); 02648 if (Sel==NULL) return; 02649 02650 // If there are no objects in the selection, or if none of the selected objects require 02651 // the attribute, then it will not be applied 02652 02653 // Obtain a pointer to the op descriptor for the operation 02654 OpDescriptor* OpDesc = OpDescriptor::FindOpDescriptor(CC_RUNTIME_CLASS(OpApplyAttribsToSelected)); 02655 02656 List AttrGroupsList; // Will contain a list of current Attribute group sets. one for each attribute 02657 // in the AttribsToApply list. Each item in this list will be a ListListItem. 02658 02659 BOOL Success; // FALSE if the operation fails 02660 BOOL AnyAttrsApplied; // FALSE if the operation has not applied any attributes 02661 02662 // Build the parameter we are about to pass to the operation 02663 ApplyAttribsToSelectedParam OpParam(&AttribsToApply, 02664 OpName, 02665 &AttrGroupsList, // One per attribute applied 02666 &Success, // Indicates if op was successful 02667 &AnyAttrsApplied); // Indicates if the operation applied 02668 // any attributes 02669 02670 02671 // Invoke the operation 02672 OpDesc->Invoke(&OpParam); 02673 02674 if (Success) 02675 { 02676 // Inform neccessary parties 02677 if (AnyAttrsApplied) 02678 { 02679 // Inform the selection that attributes have changed 02680 Sel->AttrsHaveChanged(); 02681 02682 // We've probably changed a Colour 02683 BROADCAST_TO_ALL(SelChangingMsg(SelChangingMsg::COLOURATTCHANGED)); 02684 // and the Attrib may have changed shape or summit. Who knows ? 02685 BROADCAST_TO_ALL(SelChangingMsg(SelChangingMsg::NONCOLOURATTCHANGED)); 02686 Sel->UpdateBounds(); 02687 } 02688 02689 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 02690 // Now decide which attributes in the AttribsToApply list should be made current 02691 02692 AttributeManager& AttrMgr = CurrentDoc->GetAttributeMgr(); 02693 AttrsToMakeCurrent AttribsToMakeCurrent = AttrMgr.GetAttributesToMakeCurrent(AttribsToApply, 02694 AttrGroupsList, 02695 FALSE); 02696 02697 if (AttribsToMakeCurrent == NONE) 02698 { 02699 // Allow fill tools to update after a cancel 02700 // I'm not sure if we need this ???? Ask Will 02701 BROADCAST_TO_ALL(SelChangingMsg(SelChangingMsg::NONCOLOURATTCHANGED)); 02702 } 02703 else 02704 { 02705 BOOL AttributeApplied; 02706 NodeAttributePtrItem* pAttr = (NodeAttributePtrItem*)(AttribsToApply.GetHead()); 02707 ListListItem* pAttrsGroups = (ListListItem*) (AttrGroupsList.GetHead()); 02708 while (pAttr) 02709 { 02710 AttributeApplied = (!(pAttrsGroups->list.IsEmpty())); // Empty Current attribute group list 02711 if (!AttributeApplied || (AttribsToMakeCurrent == ALL)) 02712 { 02713 // Add attribute to all current attribute groups in the list, or to the 02714 // group associated with the current tool if the list is empty. 02715 UpdateCurrentAttr(pAttr->NodeAttribPtr, 02716 FALSE, // Not a mutator 02717 &(pAttrsGroups->list), 02718 FALSE); // Don't tell world yet (too slow) 02719 } 02720 pAttr = (NodeAttributePtrItem*)(AttribsToApply.GetNext(pAttr)); 02721 pAttrsGroups = (ListListItem*)(AttrGroupsList.GetNext(pAttrsGroups)); 02722 } 02723 // Tell world current attributes have changed 02724 BROADCAST_TO_ALL(CurrentAttrChangedMsg()); 02725 } 02726 } 02727 // Tidyup 02728 AttrGroupsList.DeleteAll(); // Delete all group lists 02729 02730 // And ensure that if we've caused the SelRange to set up any delayed message 02731 // broadcasts, that it sends them now rather than at some random time in the future 02732 // when some Op just happens to end. 02733 Sel->BroadcastAnyPendingMessages(); 02734 #endif 02735 }
|
|
||||||||||||||||
|
This function would ideally live in the SelRange. It determines if the attribute can be applied to a specified object.
Definition at line 3283 of file attrmgr.cpp. 03285 { 03286 BOOL RequiresAttrib = FALSE; 03287 03288 CCRuntimeClass* NewAttrGroup; 03289 CCRuntimeClass* InSetAttrGroup; // One that's already in the list 03290 AttributeGroupItem* pAttrGrpItem; 03291 03292 BOOL InSet; 03293 03294 NodeRenderableInk* Current = pObject; 03295 03296 if (Current != NULL) 03297 { 03298 if (Current->RequiresAttrib(Attrib)) 03299 { 03300 RequiresAttrib = TRUE; 03301 03302 // Obtain the attribute group 03303 NewAttrGroup = Current->GetCurrentAttribGroup(); 03304 ERROR3IF(NewAttrGroup == NULL, "Object has a NULL attribute group"); 03305 03306 InSet = FALSE; 03307 03308 // Search the AttrGroups set to see if it's already there 03309 pAttrGrpItem = (AttributeGroupItem*)pAttrGroups->GetHead(); 03310 while(pAttrGrpItem != NULL) 03311 { 03312 InSetAttrGroup = pAttrGrpItem->AttrGroup; 03313 ERROR3IF(InSetAttrGroup == NULL, "NULL attribute group found"); 03314 if (NewAttrGroup == InSetAttrGroup) 03315 { 03316 InSet = TRUE; 03317 break; // It's already in the set don't add it 03318 } 03319 pAttrGrpItem = (AttributeGroupItem*)pAttrGroups->GetNext(pAttrGrpItem); 03320 } 03321 03322 if (!InSet) // The AttrGroup needs adding to the pAttrGroups set 03323 { 03324 // Create a new AttrGroupItem 03325 pAttrGrpItem = new AttributeGroupItem(); 03326 if (pAttrGrpItem == NULL) 03327 return FALSE; // Panic !! 03328 03329 pAttrGrpItem->AttrGroup = NewAttrGroup; 03330 03331 // And add it to our set 03332 pAttrGroups->AddHead(pAttrGrpItem); // Most recent at start of list. 03333 } 03334 } 03335 } 03336 03337 return RequiresAttrib; 03338 }
|
|
||||||||||||
|
This function would ideally live in the SelRange. It determines if the attribute can be applied to at least one object in the selection.
Definition at line 3231 of file attrmgr.cpp. 03232 { 03233 #if !defined(EXCLUDE_FROM_RALPH) 03234 SelRange* Sel = GetApplication()->FindSelection(); 03235 03236 BOOL RequiresAttrib = FALSE; 03237 03238 // Go though all the selected nodes 03239 NodeRenderableInk* Current = (NodeRenderableInk*)Sel->FindFirst(); 03240 while (Current != NULL) 03241 { 03242 // See if this node requires the attribute 03243 if (CanBeAppliedToNode(Current, Attrib, pAttrGroups)) 03244 { 03245 RequiresAttrib = TRUE; 03246 if (( |