OpUngroup Class Reference

This class represents the UnGroup operation. More...

#include <groupops.h>

Inheritance diagram for OpUngroup:

SelOperation UndoableOperation Operation MessageHandler ListItem CCObject SimpleCCObject OpUngroupSpecial List of all members.

Public Member Functions

 OpUngroup ()
 OpUngroup constructor.
void Do (OpDescriptor *)
 Performs the Ungroup operation.

Static Public Member Functions

static BOOL Init ()
 OpUngroup initialiser method.
static OpState GetState (String_256 *, OpDescriptor *)
 For finding the OpUngroup's state.

Protected Member Functions

BOOL UngroupSelectedGroups ()
 The function scans the tree and ungroups selected group nodes. It implements the main body of the OpUngroup Do function.
BOOL ParentAllowsUngroup (NodeGroup *pChild)
 Nasty BODGE code!
BOOL FindSelectedEffectAttrs () const

Detailed Description

This class represents the UnGroup operation.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
9/7/93
See also:
OpGroup Documentation: specs.doc

Definition at line 163 of file groupops.h.


Constructor & Destructor Documentation

OpUngroup::OpUngroup  ) 
 

OpUngroup constructor.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
29/9/93
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
-

Errors: -

See also:
-

Definition at line 555 of file groupops.cpp.

00555                     : SelOperation()                                
00556 {                              
00557 }


Member Function Documentation

void OpUngroup::Do OpDescriptor  )  [virtual]
 

Performs the Ungroup operation.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
16/8/93
Parameters:
OpDescriptor (unused) [INPUTS]
- [OUTPUTS]
Returns:
-

Errors: An ENSURE failure will occur if this function is called and there are no selected groups.

See also:
-

Reimplemented from Operation.

Reimplemented in OpUngroupSpecial.

Definition at line 693 of file groupops.cpp.

00694 {   
00695     if (DoStartSelOp(TRUE,TRUE))  // Try to record the selection state 
00696     {
00697         if (!UngroupSelectedGroups())
00698         {
00699             FailAndExecute(); 
00700         }    
00701     }
00702     End(); 
00703 }  

BOOL OpUngroup::FindSelectedEffectAttrs  )  const [protected]
 

Definition at line 996 of file groupops.cpp.

00997 {
00998     Range* pRange = GetApplication()->FindSelection();
00999     Node* pNode = pRange->FindFirst();
01000     while (pNode)
01001     {
01002         if (pNode->IsAGroup())
01003         {
01004             NodeAttribute* pAttr = NodeAttribute::FindFirstAppliedAttr(pNode);
01005             while (pAttr && pAttr->FindParent() == pNode)
01006             {
01007                 if (pAttr->IsEffectAttribute() && !pAttr->HasEquivalentDefaultValue(TRUE))
01008                     return TRUE;
01009 
01010                 pAttr = NodeAttribute::FindPrevAppliedAttr(pAttr);
01011             }
01012         }
01013 
01014         pNode = pRange->FindNext(pNode);
01015     }
01016 
01017     return FALSE;
01018 }

OpState OpUngroup::GetState String_256 UIDescription,
OpDescriptor
[static]
 

For finding the OpUngroup's state.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/9/93
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
The state of the OpUngroup

Errors: -

See also:
-
Notes: Karim 06/10/2000 Modified this method to check for shadowed, bevelled and contoured groups, as these cannot be ungrouped until the shadow, bevel or contour is removed.

Reimplemented in OpUngroupSpecial.

Definition at line 617 of file groupops.cpp.

00618 {
00619     OpState OpSt;
00620     
00621     String_256 DisableReason;
00622 
00623     // Obtain the current selections 
00624     Range Sel(*(GetApplication()->FindSelection()));
00625 
00626     // Determine if there are any group nodes selected,
00627     // and if so, whether they lie within controller nodes.
00628     Node* n = Sel.FindFirst();
00629 //  Node* pParentController = NULL;
00630     BOOL SelectedGroup = FALSE;
00631 //  BOOL InsideControllerNode = FALSE;
00632     while (n != NULL)
00633     {
00634         if (  n->IsSelected() && IS_A(n,NodeGroup) )
00635         {
00636 /*          pParentController = n->FindParent();
00637             if (pParentController != NULL)
00638             {
00639                 if (pParentController->IsABevelController() ||
00640 //                  pParentController->IsAShadowController() ||
00641                     pParentController->IsAContourController())
00642                 {
00643                     InsideControllerNode = TRUE;
00644                     break;
00645                 }
00646             }
00647 */
00648             SelectedGroup = TRUE;
00649             break; 
00650         }
00651         n = Sel.FindNext(n);
00652     }
00653 //  OpSt.Greyed = (InsideControllerNode || !SelectedGroup);
00654     OpSt.Greyed = !SelectedGroup;
00655     if (OpSt.Greyed)
00656     {
00657         // Load reason why operation is disabled.
00658 /*
00659         // we're inside a controller node.
00660         if (InsideControllerNode)
00661         {
00662             String_256 DisableReason(_R(IDS_GROUPINSIDECONTROLLER));
00663             *UIDescription = DisableReason;
00664         }
00665 */
00666         // No group nodes are selected.
00667 //      else if (!SelectedGroup)
00668         if(!SelectedGroup)
00669         {
00670             String_256 DisableReason(_R(IDS_NO_GROUPS_SEL));
00671             *UIDescription = DisableReason;
00672         }
00673     }
00674     return(OpSt);
00675 }

BOOL OpUngroup::Init void   )  [static]
 

OpUngroup initialiser method.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/9/93
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
TRUE if the operation could be successfully initialised FALSE if no more memory could be allocated

Errors: ERROR will be called if there was insufficient memory to allocate the operation.

See also:
-

Reimplemented from SimpleCCObject.

Reimplemented in OpUngroupSpecial.

Definition at line 577 of file groupops.cpp.

00578 {
00579     return (RegisterOpDescriptor(0,
00580                                 _R(IDS_UNGROUPOP),
00581                                 CC_RUNTIME_CLASS(OpUngroup),
00582                                 OPTOKEN_UNGROUP,
00583                                 OpUngroup::GetState,
00584                                 0,  /* help ID */
00585                                 _R(IDBBL_UNGROUPOP),
00586                                 0,  /* bitmap ID */
00587                                 0,
00588                                 SYSTEMBAR_ILLEGAL,          // For now !
00589                                 TRUE,                       // Receive messages
00590                                 FALSE,
00591                                 FALSE,
00592                                 0,
00593                                 (GREY_WHEN_NO_CURRENT_DOC | GREY_WHEN_NO_SELECTION)
00594 
00595                                  )); 
00596 }               

BOOL OpUngroup::ParentAllowsUngroup NodeGroup pChild  )  [protected]
 

Nasty BODGE code!

Author:
Karim_MacDonald (Xara Group Ltd) <camelotdev@xara.com>
Date:
09/10/2000
Parameters:
pChild the group node to check. [INPUTS]
Returns:
TRUE if our parent's type is good for ungrouping, FALSE otherwise.
Checks for the user trying to ungroup a shadowed (maybe bevelled or contoured too in future) group, disallows the operation and explains to them what the problem is/how to solve it.

Returns:
Errors: ERROR3 if the parent is an unexpected type - all such cases should never get this far into the ungroup code, they should have been caught by the GetState() checks.

Definition at line 730 of file groupops.cpp.

00731 {
00732     Node* pParent = pChild->FindParent();
00733     UINT32 MessageID = 0;
00734 
00735     if (pParent != NULL)
00736     {
00737         // if the parent is a NodeShadowController,
00738         // then post a message informing the user.
00739         if (pParent->IsABevelController())
00740             MessageID = _R(IDS_GROUPINSIDEBEVEL);
00741 PORTNOTE("other", "Ungroup can't localise effects yet")
00742 #ifndef EXCLUDE_FROM_XARALX
00743 // We don't need this clause when shadows can be localised in ungroup
00744 //      else if (pParent->IsAShadowController())    // Shadows are now PostProcessors and allow ungrouping
00745 //          MessageID = _R(IDS_GROUPINSIDESHADOW);
00746 #else
00747         else if (pParent->IsAShadowController())    // Shadows are now PostProcessors and allow ungrouping
00748             MessageID = _R(IDS_GROUPINSIDESHADOW);
00749 #endif
00750         else if (pParent->IsAContourController())
00751             MessageID = _R(IDS_GROUPINSIDECONTOUR);
00752 
00753         if(MessageID != 0)
00754         {
00755 			::InformWarning(MessageID);
00756             return FALSE;
00757         }
00758 
00759         // we must catch any group-derived nodes which make it past any ungroup checks.
00760         // the GetState() code should catch all such instances, so if execution gets here,
00761         // then something somewhere else is broken!
00762         if (pParent->IsAGroup())
00763         {
00764             ERROR3("OpUngroup::UngroupSelectedGroups; Group-derived parent node got past OpUngroup checks!");
00765             return FALSE;
00766         }
00767     }
00768 
00769     return TRUE;
00770 }

BOOL OpUngroup::UngroupSelectedGroups  )  [protected]
 

The function scans the tree and ungroups selected group nodes. It implements the main body of the OpUngroup Do function.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
22/10/93
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
TRUE if successful FALSE if the operation was aborted, or if there are no selected group nodes.
The reason the Do function was split was so that the UngroupSpecial operation could re-use the code.

Returns:
Errors: - Scope: protected
See also:
OpUngroup::Do

Definition at line 797 of file groupops.cpp.

00798 { 
00799     // Obtain the current selections
00800      
00801     Range Sel(*(GetApplication()->FindSelection()));
00802 
00803     BOOL Ungrouped = FALSE; // Set to true when we ungroup a group      
00804     BOOL bSelectGroupsHaveEffectAttrs = FALSE;
00805     Node* FirstSelectedNode = Sel.FindFirst(); 
00806     if (FirstSelectedNode != NULL) // No nodes selected so End
00807     {
00808         BOOL bLocalisePostPros = FALSE;
00809         BOOL bDeletePostPros = FALSE;
00810         EffectsStack* pStack = GetApplication()->FindSelection()->GetEffectsStack();
00811         bSelectGroupsHaveEffectAttrs = FindSelectedEffectAttrs();
00812         if ((pStack && !pStack->IsEmpty()) || bSelectGroupsHaveEffectAttrs)
00813         {
00814             bLocalisePostPros = TRUE;
00815             // If the preference is set of the user forces it by holding down Shift
00816             // We will ask the user what he wanst to do with effects
00817             ClickModifiers clickmods = ClickModifiers::GetClickModifiers();
00818             if (OpGroup::bAskBeforeFactoringEffects || clickmods.Adjust)
00819             {
00820                 OpGroup::bAskBeforeFactoringEffects = TRUE;
00821 
00822                 // We need to ask the user about removing or localising PostProcessors
00823                 INT32 ret = AskQuestion(_R(IDS_LE_ASK_UNGROUPLOCALISE), _R(IDS_LE_COPY), _R(IDS_LE_ALWAYSCOPY), _R(IDS_LE_REMOVE), _R(IDS_CANCEL));
00824                 switch (ret)
00825                 {
00826                 case 1: bLocalisePostPros = TRUE;
00827                         break;
00828                 case 2: bLocalisePostPros = TRUE;
00829                         OpGroup::bAskBeforeFactoringEffects = FALSE;
00830                         OpGroup::bLocaliseEffects = TRUE;
00831                         break;
00832                 case 3: bDeletePostPros = TRUE;
00833                         OpGroup::bLocaliseEffects = FALSE;  // ?
00834                         break;
00835                 case 4: return FALSE;
00836                         break;
00837                 }
00838             }
00839             else
00840             {
00841                 bLocalisePostPros = OpGroup::bLocaliseEffects;
00842                 bDeletePostPros = !OpGroup::bLocaliseEffects;
00843             }
00844         }
00845 
00846         // Get the current tool
00847         Tool* pTool = Tool::GetCurrent();
00848         Spread* pSelSpread = Document::GetSelectedSpread();
00849 
00850         // Get the tool to remove all its blobs before we deselect the nodes.
00851         // Only do this if the current tool dosent update itself on sel changed messages
00852         if (pSelSpread!=NULL && pTool!=NULL && !pTool->AreToolBlobsRenderedOnSelection())
00853             pTool->RenderToolBlobs(pSelSpread,NULL);
00854 
00855         // Find out which spread the node to be ungrouped is in
00856 //      Spread* pSpread = FirstSelectedNode->FindParentSpread();
00857 
00858         Node* CurrentNode = FirstSelectedNode;
00859         Node* NextCurrent;
00860         Node* GrpNode;
00861         Node* NxtGrpNode;
00862         Node* Anchor;
00863 
00864         // Ungroup all selected groups   
00865         while (CurrentNode != NULL)
00866         {
00867             NextCurrent = Sel.FindNext(CurrentNode);
00868 
00869             if (CurrentNode->IsSelected() && IS_A(CurrentNode, NodeGroup))
00870             {
00871                 // Karim 09/10/2000
00872                 // Shadows BODGE - if our parent is a NodeShadowController, then we cannot ungroup.
00873                 // Phil 2005, Shadows are different now but other controllers still disallow 
00874                 // ungrouping!
00875                 if (ParentAllowsUngroup((NodeGroup*)CurrentNode))
00876                 {
00877                     Ungrouped = TRUE;
00878 
00879                     // Karim 09/10/2000
00880                     // Invalidate region ONLY if in the middle of a background redraw UNLESS we were feathered.
00881                     // Invalidate if we are changing effects so they the changes get redrawn
00882                     BOOL RedrawNow = (CurrentNode->FindFirstChild(CC_RUNTIME_CLASS(AttrFeather))!=NULL ||
00883                                         bDeletePostPros || bLocalisePostPros ||
00884                                         bSelectGroupsHaveEffectAttrs
00885                                         );
00886                     DoInvalidateNodeRegion( ((NodeRenderableBounded*)CurrentNode), TRUE, FALSE, !RedrawNow);
00887 
00888                     // Localise any containing PostProcessors
00889                     // (This will push down common attributes into the group)
00890 /*                  // Find topmost effect applied to the current node and localise attributes
00891                     // down from there...
00892                     Node* pTopNode = EffectsStack::EscapeOldControllers(CurrentNode);
00893                     Node* pHighestLE = CurrentNode;
00894                     do
00895                     {
00896                         if (pTopNode->IsPostProcessor())
00897                             pHighestLE = pTopNode;
00898 
00899                         pTopNode = pTopNode->FindParent();
00900                     }
00901                     while (pTopNode && pTopNode->IsPostProcessor());
00902 */
00903                     if (bLocalisePostPros)
00904                     {
00905 PORTNOTETRACE("other", "Ungroup can't localise effects yet");
00906 #if !defined(EXCLUDE_FROM_XARALX)
00907                         BOOL bOK = TRUE;
00908                         bOK = bOK && OpLiveEffect::DoLocaliseEffectAttrs(this, CurrentNode);
00909                         bOK = bOK && OpLiveEffect::DoLocaliseLiveEffects(this, CurrentNode);
00910                         if (!bOK) return FALSE;
00911 #endif
00912                     }
00913                     else if (bDeletePostPros)
00914                     {
00915 PORTNOTETRACE("other", "Ungroup can't localise effects yet");
00916 #if !defined(EXCLUDE_FROM_XARALX)
00917                         if (CurrentNode->IsAnObject())
00918                         {
00919                             BOOL bOK = (OpLiveEffect::DoDeleteAllPostProcessors(this, (NodeRenderableInk*)CurrentNode, FALSE, TRUE)!=NULL);
00920                             // Effect attrs will be deleted when the group and/or postpros are deleted
00921                             // because of this we need to force the Op to redraw (see If BgRedraw above)
00922                             if (!bOK) return FALSE;
00923                         }
00924 #endif
00925                     }
00926 
00927                     // Localise the attributes 
00928                     if (!DoLocaliseCommonAttributes(((NodeGroup*)CurrentNode)))
00929                         return FALSE;
00930 
00931                     // Deselect the group node, cos we have got to remove its blobs
00932                     ((NodeGroup*)CurrentNode)->DeSelect(FALSE);
00933 
00934                     ENSURE(!(CurrentNode->IsSelected()), "Deselect failed to deselect current node");
00935 
00936                     // Hide the group node
00937                     NodeHidden* Hidden; 
00938                     if(!DoHideNode(CurrentNode, FALSE, &Hidden, FALSE))
00939                         return FALSE;
00940 
00941                     Anchor = Hidden;
00942                     ENSURE(Anchor->IsNodeHidden(),
00943                            "The parent of a hidden group node is not a NodeHidden");
00944 
00945                     // Move and select each node in turn. 
00946                     GrpNode = CurrentNode->FindFirstChild();         // Group's first child node
00947 
00948                     // Make sure that the group has at least one child
00949                     #ifdef _DEBUG
00950                     if (GrpNode == NULL)
00951                     {
00952                         TRACE( _T("Whilst ungrouping a group node without any children was found - It must be a Corel file"));
00953                     }
00954                     #endif
00955 
00956                     //ENSURE(GrpNode != NULL, "Trying to ungroup a node which has no children");
00957                     while (GrpNode != NULL)
00958                     {
00959 
00960                         // Find the next node to ungroup before we move the group node
00961                         NxtGrpNode = GrpNode->FindNext(); 
00962 
00963                         // If the node is not a NodeHidden then     
00964                         // Move the node to its new location in the tree. There is no need
00965                         // to render the node.
00966                         if (!GrpNode->IsAnAttribute() && !GrpNode->IsNodeHidden())
00967                         {
00968                             if (!DoMoveNode(GrpNode, Anchor, NEXT))
00969                                 return FALSE;
00970 
00971                             if (GrpNode->IsAnObject())
00972                                 ((NodeRenderableInk*)GrpNode)->Select(FALSE); 
00973 
00974                             Anchor = GrpNode; // Attach the next node to ungroup to the last one
00975                                               // so maintaining z ordering.
00976                         }
00977                         GrpNode = NxtGrpNode;
00978                     }
00979                 }
00980             }
00981             CurrentNode = NextCurrent; 
00982         }
00983 
00984         // Get the tool to remove all its blobs before we deselect the nodes.
00985         // Only do this if the current tool dosent update itself on sel changed messages
00986         if (pSelSpread!=NULL && pTool!=NULL && !pTool->AreToolBlobsRenderedOnSelection())
00987             pTool->RenderToolBlobs(pSelSpread,NULL);
00988     }
00989     else
00990         return (FALSE); // No nodes selected
00991 
00992     return (Ungrouped); // Ungrouped will be TRUE if we have ungrouped any groups
00993 }


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