ngscan.cpp

Go to the documentation of this file.
00001 // $Id: ngscan.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     $Header: /Camelot/kernel/ngscan.cpp 12    16/12/03 17:23 Phil $
00100     The various scans made over documents and the selected objects by the Attribute gallery.
00101 */
00102 
00103 #include "camtypes.h"
00104 
00105 #include "ngcore.h"
00106 #include "ngitem.h"
00107 #include "ngprop.h"
00108 #include "ngscan.h"
00109 #include "ngsentry.h"
00110 
00111 #include "extender.h"
00112 #include <algorithm>
00113 
00114 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00115 //#include "undoop.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00116 #include "objchge.h"
00117 //#include "ink.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00118 //#include "nodeattr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00119 #include "layer.h"
00120 #include "keypress.h"
00121 #include "nodebmp.h"        // for NodeBitmap
00122 #include "nodershp.h"       // for NodeRegularShape
00123 #include "ophist.h"
00124 
00125 //#include "cxfrech.h"      // TemplateAttribute - in camtypes.h [AUTOMATICALLY REMOVED]
00126 //#include "attrval.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00127 #include "userattr.h"
00128 #include "tmpltatr.h"
00129 
00130 //#include "mario.h"
00131 
00132 #include "nodershp.h"       // for NodeRegularShape
00133 #include "nodebmp.h"        // for NodeBitmap
00134 
00135 // for text story stuff
00136 #include "nodetxts.h"
00137 #include "nodetxtl.h"
00138 #include "nodetext.h"
00139 
00140 //#include "sliceres.h"
00141 
00142 #ifdef _DEBUG
00143 #undef THIS_FILE
00144 static char BASED_CODE THIS_FILE[] = __FILE__;
00145 #endif
00146 
00147 DECLARE_SOURCE("$Revision: 1282 $");
00148 
00149 #define new CAM_DEBUG_NEW
00150 
00151 // This is shared between all instances of AllowOpScan so an operation can make
00152 // multiple allow scans on the same OCP.
00153 ObjChangeParam AllowOpScan::m_OCP;
00154 
00155 
00156 /********************************************************************************************
00157 >   BaseSelectScan::BaseSelectScan(BaseSelectScan::Change eChange, BOOL fQuiet = FALSE)
00158 
00159     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00160     Created:    27/5/99
00161     Inputs:     eChange         ---     how to change the selection: TOGGLE, DESELECT,
00162                                         SELECT, SELECT_EXCLUSIVE
00163                 fQuiet          ---     don't redraw blobs or broadcast messages
00164     Purpose:    Constructs an BaseSelectScan object.
00165     SeeAlso:    NodeScan
00166 ********************************************************************************************/
00167 
00168 BaseSelectScan::BaseSelectScan(BaseSelectScan::Change eChange, BOOL fQuiet)
00169   : NodeScan(&theSelectedDocument),
00170     m_eChange(eChange),
00171     m_fShout(!fQuiet),
00172     m_nAffected(0)
00173 {  
00174     // Empty.
00175 }
00176 
00177 
00178 
00179 /********************************************************************************************
00180 >   virtual BOOL BaseSelectScan::OnSelectable(NodeRenderable* pRender)
00181 
00182     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00183     Created:    27/5/99
00184     Inputs:     pRender ---     the object whose selection state is to be changed
00185     Returns:    The previous selection state of the object.
00186     Purpose:    Helper function for BaseSelectScan derivatives that change the selection
00187                 state of renderable nodes.
00188 ********************************************************************************************/
00189 
00190 BOOL BaseSelectScan::OnSelectable(NodeRenderable* pRender)
00191 {
00192     // Check for the effects of the layer containing the object.
00193     Node* pNode = pRender;
00194     while (pNode != 0)
00195     {
00196         if (pNode->IsLayer())
00197         {
00198             // Quit now if the layer is invisible or locked.
00199             Layer* pLayer = (Layer*) pNode;
00200             if ( pLayer->IsLocked()) return FALSE;
00201             break;
00202         }
00203 
00204         pNode = pNode->FindParent();
00205     }
00206 
00207     // Perform the selection change.
00208     BOOL fPrevSel = pRender->IsSelected();
00209     switch (m_eChange)
00210     {
00211     case TOGGLE:
00212         if (fPrevSel)
00213             pRender->DeSelect(m_fShout);
00214         else
00215             pRender->Select(m_fShout);
00216         break;
00217 
00218     case DESELECT:
00219         pRender->DeSelect(m_fShout);
00220         break;
00221 
00222     default:
00223         pRender->Select(m_fShout);
00224         break;
00225     }
00226 
00227     // Keep count of how many we've changed.
00228     ++m_nAffected;
00229     return fPrevSel;
00230 }
00231 
00232 
00233 
00234 /********************************************************************************************
00235 >   virtual BOOL BaseSelectScan::Pre()
00236 
00237     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00238     Created:    27/5/99
00239     Inputs:     pNode       ---     the current node in the scan
00240     Purpose:    Clears the selection first if the new state isn't "toggle" and the
00241                 gallery ctrl-key isn't down.
00242     Returns:    TRUE, continue scanning.
00243     SeeAlso:    NodeScan
00244 ********************************************************************************************/
00245 
00246 BOOL BaseSelectScan::Pre()
00247 {
00248     // If selecting exclusively then clear the selection of all objects first and count
00249     // them towards a call to Update().
00250     if (m_eChange == SELECT_EXCLUSIVE)
00251     {
00252         m_nAffected += (INT32) GetApplication()->FindSelection()->Count();
00253         NodeRenderableInk::DeselectAll(m_fShout, FALSE);
00254     }
00255 
00256     return TRUE;
00257 }
00258 
00259 
00260 
00261 /********************************************************************************************
00262 >   virtual BOOL BaseSelectScan::Do(Node* pNode)
00263 
00264     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00265     Created:    27/5/99
00266     Inputs:     pNode       ---     the current node in the scan
00267     Returns:    TRUE, continue scanning.
00268     Purpose:    Called by SelectScan when the 'select' action is executed.  Tests
00269                 the given node for membership of each highlighted set and changes it's
00270                 selection status accordingly.
00271     SeeAlso:    BaseSelectScan
00272 ********************************************************************************************/
00273 
00274 BOOL BaseSelectScan::Do(Node* pNode)
00275 {
00276     // Let OnSelectable() control the continuation of the scan.
00277     return pNode->IsNodeRenderableClass() ? OnSelectable((NodeRenderable*) pNode) : TRUE;
00278 }
00279 
00280 
00281 
00282 /********************************************************************************************
00283 >   virtual BOOL BaseSelectScan::Post()
00284 
00285     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00286     Created:    27/5/99
00287     Purpose:    Called by BaseSelectScan after the selection is changed.  Updates the
00288                 application's selection range object.
00289     SeeAlso:    NodeScan
00290 ********************************************************************************************/
00291 
00292 BOOL BaseSelectScan::Post()
00293 {
00294     if (m_nAffected != 0) GetApplication()->FindSelection()->Update(m_fShout);
00295     return TRUE;
00296 }
00297 
00298 
00299 
00300 /********************************************************************************************
00301 >   SelectScan::SelectScan(SGNameItem* pItem, BaseSelectScan::Change eChange,
00302                            BOOL fQuiet = FALSE)
00303 
00304     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00305     Created:    27/5/99
00306     Inputs:     pItem           ---     the set of objects to change the selection of
00307                 eChange         ---     how to change the selection: TOGGLE, DESELECT,
00308                                         SELECT, SELECT_EXCLUSIVE
00309     Purpose:    Constructs an SelectScan object.
00310     SeeAlso:    BaseSelectScan
00311 ********************************************************************************************/
00312 
00313 SelectScan::SelectScan(SGNameItem* pItem, BaseSelectScan::Change eChange, BOOL fQuiet)
00314   : BaseSelectScan(eChange, fQuiet),
00315     m_pItem(pItem)
00316 {  
00317     // Empty.
00318 }
00319 
00320 
00321 
00322 /********************************************************************************************
00323 >   virtual BOOL SelectScan::OnSelectable(NodeRenderable* pRender)
00324 
00325     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00326     Created:    27/5/99
00327     Inputs:     pRender     ---     the current renderable node in the selection scan
00328     Returns:    TRUE, continue scanning.
00329     Purpose:    Called by SelectScan when the 'select' action is executed.  Tests
00330                 the given node for membership of each highlighted set and changes it's
00331                 selection status accordingly.
00332     SeeAlso:    BaseSelectScan
00333 ********************************************************************************************/
00334 
00335 BOOL SelectScan::OnSelectable(NodeRenderable* pRender)
00336 {
00337     // If the node is a member then change its selection state.
00338     if (m_pItem->IsMember(pRender))
00339     {
00340         // what it does is look at the text story if we are trying to select a text char
00341         // and we will be selecting the story
00342         // then just set the story to the end result
00343         // rather than selecting one char at a time (sjk 1/8/00)
00344         if (pRender->IsATextChar() && m_eChange != TOGGLE)
00345         {
00346             Node * pStory = pRender->FindParent(CC_RUNTIME_CLASS(TextStory));
00347             if (pStory && m_pItem->IsMember(pStory))
00348             {
00349                 BOOL TurnOff = (m_eChange == DESELECT);
00350 
00351                 if (pStory->IsSelected() != TurnOff)
00352                 {
00353                     if (TurnOff)
00354                         pRender->DeSelect(m_fShout);
00355                     else
00356                         pRender->Select(m_fShout);
00357                 }
00358 
00359                 // keep the counts right
00360                 m_nAffected++;
00361 
00362                 return TRUE;
00363             }
00364         }
00365 
00366         BaseSelectScan::OnSelectable(pRender);
00367     }
00368     return TRUE;
00369 }
00370 
00371 
00372 
00373 /********************************************************************************************
00374 >   SelectUnionScan::SelectUnionScan(BaseSelectScan::Change eChange)
00375 
00376     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00377     Created:    27/5/99
00378     Inputs:     eChange         ---     how to change the selection: TOGGLE, RESET,
00379                                         SET, SET_EXCLUSIVE
00380     Purpose:    Constructs an SelectUnionScan object.
00381     SeeAlso:    BaseSelectScan
00382 ********************************************************************************************/
00383 
00384 SelectUnionScan::SelectUnionScan(BaseSelectScan::Change eChange)
00385   : BaseSelectScan(eChange)
00386 {  
00387     // Empty.
00388 }
00389 
00390 
00391 
00392 /********************************************************************************************
00393 >   virtual BOOL SelectUnionScan::OnSelectable(NodeRenderable* pRender)
00394 
00395     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00396     Created:    27/5/99
00397     Inputs:     pRender     ---     the current renderable node in the scan
00398     Purpose:    Called by SelectUnionScan when the 'select' action is executed.  Tests
00399                 the given node for membership of the highlighted SGNameItems and changes
00400                 its selection status if it is a member of any.
00401     SeeAlso:    BaseSelectScan
00402 ********************************************************************************************/
00403 
00404 BOOL SelectUnionScan::OnSelectable(NodeRenderable* pRender)
00405 {
00406     // If it's a member of any highlighted SGNameItem then change its selection.
00407     if (Test(pRender, Test::IS_MEMBER).ForEach() != 0)
00408         BaseSelectScan::OnSelectable(pRender);
00409 
00410     return TRUE;
00411 }
00412 
00413 
00414 
00415 /********************************************************************************************
00416 >   SelectUnionScan::Test::Test(NodeRenderable* pRender, SelectUnionScan::Test::Question eQ)
00417 
00418     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00419     Created:    27/5/99
00420     Inputs:     pRender     ---     the renderable node to test for membership of any
00421                                     highlighted SGNameItems.
00422                 eQ          ---     SelectUnionScan::Test::IS_MEMBER or IS_NON_MEMBER.
00423     Purpose:    Constructs an SelectUnionScan::Test object.
00424     SeeAlso:    DocScan; BaseSelectScan
00425 ********************************************************************************************/
00426 
00427 SelectUnionScan::Test::Test(NodeRenderable* pRender, SelectUnionScan::Test::Question eQ)
00428   : NameItemIter(NameItemIter::HIGHLIGHTED_ITEMS),
00429     m_pRender(pRender),
00430     m_nXor((BOOL) eQ)
00431 {
00432     // Empty.
00433 }
00434 
00435 
00436 
00437 /********************************************************************************************
00438 >   virtual BOOL SelectUnionScan::Test::Do(SGNameItem* pItem)
00439 
00440     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00441     Created:    27/5/99
00442     Inputs:     pItem           ---     the current item in the iteration
00443     SeeAlso:    BaseSelectScan; SelectUnionScan::Test
00444 ********************************************************************************************/
00445 
00446 BOOL SelectUnionScan::Test::Do(SGNameItem* pItem)
00447 {
00448     return pItem->IsMember(m_pRender) ^ m_nXor;
00449 }
00450 
00451 
00452 
00453 /********************************************************************************************
00454 >   SelectIntersectScan::SelectIntersectScan(BaseSelectScan::Change eChange)
00455 
00456     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00457     Created:    27/5/99
00458     Inputs:     eChange         ---     how to change the selection: TOGGLE, RESET,
00459                                         SET, SET_EXCLUSIVE
00460     Purpose:    Constructs an SelectIntersectScan object.
00461     SeeAlso:    DocScan; BaseSelectScan
00462 ********************************************************************************************/
00463 
00464 SelectIntersectScan::SelectIntersectScan(BaseSelectScan::Change eChange)
00465   : SelectUnionScan(eChange)
00466 {
00467     // Empty.
00468 }
00469 
00470 
00471 
00472 /********************************************************************************************
00473 >   virtual BOOL SelectIntersectScan::Do(NodeRenderable* pRender)
00474 
00475     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00476     Created:    27/5/99
00477     Inputs:     pNode       ---     the current node in the scan
00478     Purpose:    Called by SelectIntersectScan when the 'intersect' action is executed.  Tests
00479                 the given node for membership of all highlighted sets and changes it's
00480                 selection status accordingly.
00481     SeeAlso:    BaseSelectScan
00482 ********************************************************************************************/
00483 
00484 BOOL SelectIntersectScan::OnSelectable(NodeRenderable* pRender)
00485 {
00486     // If it's a member of every highlighted SGNameItem then change its selection.
00487     if (Test(pRender, Test::IS_NON_MEMBER).ForEach() == 0)
00488         BaseSelectScan::OnSelectable(pRender);
00489 
00490     return TRUE;
00491 }
00492 
00493 
00494 
00495 /********************************************************************************************
00496 >   AllowOpScan::AllowOpScan(UndoableOperation* pOp, NodeScan::Source* ps)
00497 
00498     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00499     Created:    27/5/99
00500     Inputs:     pOp     ---     the UndoableOperation to scan for "allowance".
00501                 ps  ---         the source for nodes to scan over, by default the
00502                                 'selected' document's tree.
00503     Purpose:    Constructs an AllowOpScan object, which checks AllowOp for the given 
00504                 operation on all nodes in the tree which are members of highlighted
00505                 items in the 'Used Names' group of the Name Gallery.  Defines the 
00506                 ObjChangeParam as STARTING.
00507     SeeAlso:    NodeScan; ObjChangeParam; UndoableOperation
00508 ********************************************************************************************/
00509 
00510 AllowOpScan::AllowOpScan(UndoableOperation* pOp, NodeScan::Source* ps)
00511   : UndoableNodeScan(pOp, ps)
00512 {
00513     // Set up the change flags etc.
00514     m_OCP.Define(OBJCHANGE_STARTING, ObjChangeFlags(FALSE, FALSE, FALSE, TRUE), 0, m_pOp);
00515 }
00516 
00517 
00518 
00519 /********************************************************************************************
00520 >   virtual BOOL AllowOpScan::Do(Node* pNode)
00521 
00522     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00523     Created:    27/5/99
00524     Inputs:     pNode   ---     the node to call AllowOp for if it is a member of
00525                                 a highlighted set in the Name Gallery.
00526     Purpose:    Tests if the given node is a member of a set that the user has
00527                 highlighted in the Name Gallery and if so, calls AllowOp on it.
00528     SeeAlso:    AllowOpScan::IsLitUsedName; Node::AllowOp
00529 ********************************************************************************************/
00530 
00531 BOOL AllowOpScan::Do(Node* pNode)
00532 {
00533     // If the node is a highlighted member of a "used names" set then call it's AllowOp
00534     // function and stop the iteration if it refuses the op.  If it isn't a member then
00535     // ignore it.
00536     return IsLitUsedName(pNode).ForEach() == 0 || pNode->AllowOp(&m_OCP);
00537 }
00538 
00539 
00540 
00541 /********************************************************************************************
00542 >   virtual BOOL AllowOpScan::Update()
00543 
00544     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00545     Created:    27/5/99
00546     Inputs:     pOp     ---     the UndoableOperation to scan for "allowance".
00547                 pOCP    ---     the ObjChangeParam block to use
00548     Purpose:    Defines the ObjChangeParam as FINISHED and calls UpdateChangedNodes.
00549     Returns:    TRUE if successful.
00550     SeeAlso:    ObjChangeParam; UndoableOperation
00551 ********************************************************************************************/
00552 
00553 BOOL AllowOpScan::Update()
00554 {
00555     // Update all parents of changed nodes.
00556     m_OCP.Define(OBJCHANGE_FINISHED, ObjChangeFlags(FALSE, FALSE, FALSE, TRUE), 0, m_pOp);
00557     return m_pOp->UpdateChangedNodes(&m_OCP);
00558 
00559 }
00560 
00561 
00562 
00563 /********************************************************************************************
00564 >   AllowOpScan::IsLitUsedName::IsLitUsedName(Node* pNode)
00565 
00566     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00567     Created:    27/7/99
00568     Inputs:     pNode       ---     the node to test for membership of a set within
00569                                     the 'Used Names' group of the Name Gallery.
00570     Purpose:    Tests if the given Node is a member of a set within the Attribute gallery.
00571     SeeAlso:    AllowOpScan; NameItemIter
00572 ********************************************************************************************/
00573 
00574 AllowOpScan::IsLitUsedName::IsLitUsedName(Node* pNode)
00575   : NameIterOp(pNode)
00576 {
00577     // Empty.   
00578 }
00579 
00580 
00581 
00582 /********************************************************************************************
00583 >   virtual BOOL AllowOpScan::IsLitUsedName::Do(SGNameItem* pItem)
00584 
00585     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00586     Created:    27/7/99
00587     Inputs:     pItem       ---     the set item to test for membership
00588     Purpose:    Tests if the Node passed to the constructor is a member of the given
00589                 set item.
00590     SeeAlso:    AllowOpScan::IsLitUsedName; SGNameItem::IsMember
00591 ********************************************************************************************/
00592 
00593 BOOL AllowOpScan::IsLitUsedName::Do(SGNameItem* pItem)
00594 {
00595     // Quit as soon as we find a set item the object is a member of.  ForEach will return
00596     // the address of the first set item the object is within.
00597     return !pItem->IsMember(m_pNode);
00598 }
00599 
00600 
00601 
00602 /********************************************************************************************
00603 >   AllowOpSingleScan::AllowOpSingleScan(UndoableOperation* pOp, NodeScan::Source* ps,
00604                                          const StringBase& strName)
00605     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00606     Created:    27/5/99
00607     Inputs:     pOp     ---     the UndoableOperation to scan set strName for "allowance".
00608                 ps      ---     the source for candidate nodes to scan over, by default the
00609                                 'selected' document's tree.
00610                 strName ---     name of the set whose members are to be scanned
00611     Purpose:    Constructs an AllowOpSingleScan object, which checks AllowOp for the given 
00612                 operation on all nodes in the tree which are members of the specified
00613                 set.
00614     SeeAlso:    NodeScan; AllowOpScan; OpDeleteNames; ObjChangeParam; UndoableOperation
00615 ********************************************************************************************/
00616 
00617 AllowOpSingleScan::AllowOpSingleScan(UndoableOperation* pOp, NodeScan::Source* ps,
00618                                      const StringBase& strName)
00619   : AllowOpScan(pOp, ps),
00620     m_strName(strName),
00621     m_pUsedNames(NameGallery::Instance()->GetUsedNames())
00622 {
00623     ERROR3IF(m_pUsedNames == 0, "AllowOpSingleScan::AllowOpSingleScan: no used names");
00624 }
00625 
00626 
00627 
00628 /********************************************************************************************
00629 >   virtual BOOL AllowOpSingleScan::Do(Node* pNode)
00630 
00631     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00632     Created:    27/5/99
00633     Inputs:     pNode   ---     the node to call AllowOp for if it is a member of
00634                                 a specified set.
00635     Purpose:    Tests if the given node is a member of a specified and if so, calls
00636                 AllowOp on it.
00637     SeeAlso:    AllowOpScan::Do; SGUsedNames::IsMember; Node::AllowOp
00638 ********************************************************************************************/
00639 
00640 BOOL AllowOpSingleScan::Do(Node* pNode)
00641 {
00642     // Stop iterating if the node is a member which doesn't allow the op.
00643     return !m_pUsedNames->IsMember(pNode, m_strName) || pNode->AllowOp(&m_OCP);
00644 }
00645 
00646 
00647 
00648 /********************************************************************************************
00649 >   static BOOL ApplyNameToNode(const StringBase& strName, Node* pNode,
00650                                 UndoableOperation* pOp, INT32 BarNo)
00651 
00652     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00653     Created:    27/5/99
00654     Inputs:     strName     ---     the node to apply a name to
00655                 pNode       ---     the name to apply to the node
00656                 pOp         ---     the Operation context in which to manipulate nodes
00657                 BarNo       ---     the bar number if it has one
00658     Returns:    TRUE if successful.
00659     Purpose:    Helper function to create a new Wix object name attribute and attach
00660                 it to the given node in an undoable way.
00661     Errors:     Out of memory.
00662     SeeAlso:    ApplyScan
00663 ********************************************************************************************/
00664 
00665 static BOOL ApplyNameToNode(const StringBase& strName, Node* pNode, UndoableOperation* pOp, INT32 BarNo)
00666 {
00667     // Try to create a new object name attribute to apply to the target node.
00668     TemplateAttribute* pta;
00669     String_256 BarName = "";
00670 
00671     if (BarNo >= 0)
00672     {
00673         BarName.MakeMsg(_R(IDS_BARNAME), BarNo+1);
00674     }
00675 
00676     ALLOC_WITH_FAIL(pta, (new TemplateAttribute(TA_NAME, BarNo >= 0 ? BarName : _T("") , strName)), pOp);
00677     ERRORIF(pta == 0, _R(IDE_NOMORE_MEMORY), FALSE);
00678 
00679     // If the target node is an object, check that the attribute type is required by it,
00680     // and make a note for the attribute manager of the object being applied to.
00681     if (pNode->IsAnObject())
00682     {
00683         NodeRenderableInk* pObj = (NodeRenderableInk*) pNode;
00684         if (!pObj->RequiresAttrib(pta))
00685         {
00686             // (No objects reject Wix attributes, AFAIK)
00687             TRACEUSER( "JustinF", _T("ApplyNameToNode: %s failed RequireAttrib at 0x%p\n"),
00688                                             pObj->GetRuntimeClass()->m_lpszClassName, pObj);
00689             delete pta;
00690             return FALSE;
00691         }
00692 
00693         AttributeManager::pLastNodeAppliedTo = pObj;
00694     }
00695 
00696     // Attach the new attribute and make a note for the AttributeManager.
00697     pta->AttachNode(pNode, FIRSTCHILD);
00698 
00699 /*              *** DUBIOUS TEXT BODGE ***
00700     // If we are applying the attribute to a node which discards its attribute children
00701     // (like the caret) then we should not generate any undo for the operation.
00702     if (m_pNode->DiscardsAttributeChildren()) SucceedAndDiscard();
00703 
00704     // JCF: this is a bodge for the text tool, copied from 
00705     // OpApplyAttribToSelected::ApplyToSelection:-
00706     //
00707     // "EOL nodes can now have attributes, but the last EOL cannot
00708     // be selected by the user, causing the text tool to show <multiple>
00709     // when it shouldn't really.  So if the last node in the range is
00710     // the node before the last EOL in a text story then we apply the
00711     // attribute to the EOL too."
00712     Node* pLastNode = selRange.FindLast();
00713     if (pLastNode != 0 && pLastNode->IsAVisibleTextNode())
00714     {
00715         // "Alternative approach to fix other EOLNode problems that have appeared, ie.
00716         // (Bugs 5371 & 5372). If the AbstractTextChar following the last selected node
00717         // is an EOLNode then apply to it too."
00718         AbstractTextChar* pNextChr =
00719             (AbstractTextChar*) pLastNode->FindNext(CC_RUNTIME_CLASS(AbstractTextChar));
00720         if (pNextChr != 0 && pNextChr->IsAnEOLNode() && !DoApply(pNextChr, pAttrib, pSets))
00721         {
00722             delete pAttrib;
00723             FailAndExecute();
00724             End();
00725             return;
00726         }
00727     }
00728 */
00729     // Create an action to hide the new attribute when we Undo.
00730     HideNodeAction* pHideAct;
00731     if (AC_FAIL == HideNodeAction::Init(pOp, pOp->GetUndoActions(),
00732                                         pta, TRUE, (Action**) &pHideAct))
00733     {
00734         pta->CascadeDelete();
00735         delete pta;
00736         return FALSE;
00737     }
00738 
00739     // Success.
00740     return TRUE;
00741 }
00742 
00743 
00744 
00745 /********************************************************************************************
00746 >   ApplyScan::ApplyScan(UndoableOperation* pOp, NodeScan::Source* ps)
00747 
00748     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00749     Created:    27/5/99
00750     Inputs:     pOp         ---     the UndoableOperation that is the context for this
00751                                     scanning
00752                 ps          ---     the source for nodes to scan over
00753     Purpose:    Constructs an ApplyScan object
00754     SeeAlso:    UndoableNodeScan; OpApplyNames; ApplyScan::ApplyItems
00755 ********************************************************************************************/
00756 
00757 ApplyScan::ApplyScan(UndoableOperation* pOp, NodeScan::Source* ps)
00758   : UndoableNodeScan(pOp, ps)
00759 {
00760     // Empty.
00761 }
00762 
00763 
00764 
00765 /********************************************************************************************
00766 >   virtual BOOL ApplyScan::Do(Node* pNode)
00767 
00768     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00769     Created:    27/5/99
00770     Inputs:     pNode       ---     the node to apply names to
00771     Purpose:    Applies names highlighted in the Attribute gallery to the given node.
00772     SeeAlso:    OpApplyNames; ApplyScan::ApplyItems
00773 ********************************************************************************************/
00774 
00775 BOOL ApplyScan::Do(Node* pNode)
00776 {
00777     // Apply all highlighted 'Used Names' to the node.
00778     return ApplyItems(pNode, m_pOp).ForEach() == 0;
00779 }
00780 
00781 
00782 
00783 /********************************************************************************************
00784 >   ApplyScan::ApplyItems::ApplyItems(Node* pNode, UndoableOperation* pOp)
00785 
00786     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00787     Created:    27/5/99
00788     Inputs:     pNode       ---     the node to apply highlighted items' names
00789                 pOp         ---     the Operation context in which to manipulate the attrs.
00790     SeeAlso:    OpApplyNames::Do
00791 ********************************************************************************************/
00792 
00793 ApplyScan::ApplyItems::ApplyItems(Node* pNode, UndoableOperation* pOp)
00794   : NameIterOp(pNode, pOp)
00795 {
00796     // Empty.
00797 }
00798 
00799 
00800 
00801 /********************************************************************************************
00802 >   BOOL ApplyScan::ApplyItems::Do(SGNameItem* pItem)
00803 
00804     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00805     Created:    27/5/99
00806     Inputs:     pItem       ---     the highlighted set item whose name is to be applied
00807     Purpose:    Applies the Wix ObjectName attributes that apply to objects.
00808     SeeAlso:    OpApplyNames
00809 ********************************************************************************************/
00810 
00811 BOOL ApplyScan::ApplyItems::Do(SGNameItem* pItem)
00812 {
00813     // If the object is already a member of the item's set then ignore it.
00814     if (pItem->IsMember(m_pNode)) return TRUE;
00815 
00816     // Extract the name from the item and apply it.
00817     String_256 strName;
00818     pItem->GetNameText(&strName);
00819     return ApplyNameToNode(strName, m_pNode, m_pOp, pItem->m_BarNumber);
00820 }
00821 
00822 
00823 
00824 /********************************************************************************************
00825 >   ApplySingleScan::ApplySingleScan(UndoableOperation* pOp, NodeScan::Source* ps,
00826                                      const StringBase& strName)
00827 
00828     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00829     Created:    27/5/99
00830     Inputs:     pOp         ---     the UndoableOperation that is the context for this
00831                                     scanning
00832                 ps          ---     the source for nodes to scan over
00833                 strName     ---     the name to apply to the selected objects
00834     Purpose:    Constructs an ApplySingleScan object
00835     SeeAlso:    ApplyScan; UndoableNodeScan; OpApplyNames::DoWithParam
00836 ********************************************************************************************/
00837 
00838 ApplySingleScan::ApplySingleScan(UndoableOperation* pOp, NodeScan::Source* ps,
00839                                  const StringBase& strName)
00840   : ApplyScan(pOp, ps),
00841     m_strName(strName)
00842 {
00843     // Empty.
00844 }
00845 
00846 
00847 
00848 /********************************************************************************************
00849 >   virtual BOOL ApplySingleScan::Do(Node* pNode)
00850 
00851     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00852     Created:    27/5/99
00853     Inputs:     pNode       ---     the node to apply the name to
00854     Purpose:    Applies the name passed to the constructor to all the selected objects.
00855     SeeAlso:    ApplyScan; UndoableNodeScan; OpApplyNames::DoWithParam
00856 ********************************************************************************************/
00857 
00858 BOOL ApplySingleScan::Do(Node* pNode)
00859 {
00860     return ApplyNameToNode(m_strName, pNode, m_pOp, -1);
00861 }
00862 
00863 
00864 
00865 /********************************************************************************************
00866 >   static NodeSetProperty* ApplyPropToNode(const StringBase& strName, Node* pNode,
00867                                             NodeSetProperty* pCopyPropNode,
00868                                             UndoableOperation* pOp)
00869 
00870     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00871     Created:    27/5/99
00872     Inputs:     strName     ---     the node to 'apply' a property to
00873                 pNode       ---     the property to 'apply' to the node
00874                 pOp         ---     the Operation context in which to manipulate nodes
00875                 pCopyPropNode   ---     the NodeSetProperty whose properties are to be
00876                                         copied into the 'applied' property, or null 
00877                                         for no copy and default properties.
00878     Returns:    Pointer to the newly 'applied' NodeSetProperty, or null for failure.
00879     Purpose:    Helper function to create a new NodeSetProperty, with default properties,
00880                 and attach it to the given node in an undoable way.
00881     Errors:     Out of memory.
00882     SeeAlso:    ApplyPropScan
00883 ********************************************************************************************/
00884 
00885 static NodeSetProperty* ApplyPropToNode(const StringBase& strName, Node* pNode,
00886                                         NodeSetProperty* pCopyPropNode,
00887                                         UndoableOperation* pOp)
00888 {
00889     // If the set sentinel already has a NodeSetProperty for the given name then
00890     // do nothing.
00891     NodeSetProperty* psp =
00892             Document::GetSelected()->GetSetSentinel()->FindPropertyNode(strName);
00893     if (psp != 0) return psp;
00894 
00895     // Try to create a new property node to 'apply' to the sentinel.
00896     ALLOC_WITH_FAIL(psp, (new NodeSetProperty(strName)), pOp);
00897     ERRORIF(psp == 0, _R(IDE_NOMORE_MEMORY), 0);
00898 
00899     // Try to make a bunch of default or copied properties for it.
00900     NodeSetProperty * fOK=psp; // we use this as a boolean flag
00901     ALLOC_WITH_FAIL(psp, 
00902                     ((pCopyPropNode != 0 ? psp->CopyProperties(pCopyPropNode)
00903                                         : psp->CreateDefaults())?psp:NULL),
00904                     pOp);
00905     if (!fOK)
00906     {
00907         delete psp;
00908         ERROR1RAW(_R(IDE_NOMORE_MEMORY));
00909         return 0;
00910     }
00911 
00912     // Attach the new property and create an action to hide it when we Undo.
00913     HideNodeAction* pHideAct;
00914     psp->AttachNode(pNode, LASTCHILD);
00915     if (AC_FAIL == HideNodeAction::Init(pOp, pOp->GetUndoActions(),
00916                                         psp, TRUE, (Action**) &pHideAct))
00917     {
00918         psp->CascadeDelete();
00919         delete psp;
00920         return 0;
00921     }
00922 
00923     // Success.
00924     return psp;
00925 }
00926 
00927 
00928 
00929 /********************************************************************************************
00930 >   ApplyPropScan::ApplyPropScan(UndoableOperation* pOp, NodeScan::Source* ps,
00931                                  const StringBase& strName,
00932                                  NodeSetProperty* pCopyPropNode = 0)
00933 
00934     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00935     Created:    27/5/99
00936     Inputs:     pOp             ---     the UndoableOperation that is the context for this
00937                                         scanning
00938                 strName         ---     the name to apply to the selected objects
00939                 pCopyPropNode   ---     the NodeSetProperty whose properties are to be
00940                                         copied into the 'applied' property, or null 
00941                                         for no copy and default properties.
00942     Purpose:    Constructs an ApplyPropScan object
00943     SeeAlso:    ApplySingleScan; ApplyScan; UndoableNodeScan; OpApplyNames::DoWithParam
00944 ********************************************************************************************/
00945 
00946 ApplyPropScan::ApplyPropScan(UndoableOperation* pOp, const StringBase& strName,
00947                              NodeSetProperty* pCopyPropNode)
00948   : ApplySingleScan(pOp, &theSetSentinel, strName),
00949     m_pCopyPropNode(pCopyPropNode)
00950 {
00951     // Empty.
00952 }
00953 
00954 
00955 
00956 /********************************************************************************************
00957 >   virtual BOOL ApplyPropScan::Do(Node* pNode)
00958 
00959     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00960     Created:    27/5/99
00961     Inputs:     pNode       ---     the node to apply the name to
00962     Purpose:    Applies a default property to the given node (ie. the set sentinel).
00963     SeeAlso:    ApplySingleScan; ApplyScan; UndoableNodeScan; OpApplyNames::DoWithParam
00964 ********************************************************************************************/
00965 
00966 BOOL ApplyPropScan::Do(Node* pNode)
00967 {
00968     return ApplyPropToNode(m_strName, pNode, m_pCopyPropNode, m_pOp) != 0;
00969 }
00970 
00971 
00972 
00973 /********************************************************************************************
00974 >   HideScan::HideScan(UndoableOperation* pOp, NodeScan::Source* ps)
00975 
00976     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00977     Created:    27/5/99
00978     Inputs:     pOp     ---     the UndoableOperation that is the context for this
00979                                 scanning
00980     Purpose:    Constructs a HideScan object, which scans through the tree
00981                 for objects which are members of highlighted 'Used Names' sets in the
00982                 Name Gallery and excludes them from their sets by hiding the Wix
00983                 ObjectName attributes which apply to them.
00984     SeeAlso:    UndoableNodeScan; OpDeleteNames; HideScan::HideItems
00985 ********************************************************************************************/
00986 
00987 HideScan::HideScan(UndoableOperation* pOp, NodeScan::Source* ps)
00988   : UndoableNodeScan(pOp, ps)
00989 {
00990     // Empty.
00991 }
00992 
00993 
00994 
00995 /********************************************************************************************
00996 >   virtual BOOL HideScan::Do(Node* pNode)
00997 
00998     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00999     Created:    27/5/99
01000     Inputs:     pNode       ---     the node to test for membership of a highlighted set
01001                                     and if necessary exclude it from the set
01002     Purpose:    Excludes the given node from any highlighted sets in the Name Gallery.
01003     SeeAlso:    OpDeleteNames; HideScan::HideItems
01004 ********************************************************************************************/
01005 
01006 BOOL HideScan::Do(Node* pNode)
01007 {
01008     // If the object is a highlighted member of a "used names" set then hide its
01009     // Wix ObjectName attribute.
01010     return HideItems(pNode, m_pOp).ForEach() == 0;
01011 }
01012 
01013 
01014 
01015 /********************************************************************************************
01016 >   HideScan::HideItems::HideItems(Node* pNode, UndoableOperation* pOp)
01017 
01018     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01019     Created:    27/5/99
01020     Inputs:     pNode       ---     the node to test for membership of a highlighted set
01021                                     and if necessary exclude it from the set
01022                 pOp         --      the Operation context in which to manipulate the attrs.
01023     Purpose:    Excludes the given node from any highlighted sets in the Name Gallery.
01024     SeeAlso:    OpDeleteNames
01025 ********************************************************************************************/
01026 
01027 HideScan::HideItems::HideItems(Node* pNode, UndoableOperation* pOp)
01028   : NameIterOp(pNode, pOp)
01029 {
01030     // Empty.
01031 }
01032 
01033 
01034 
01035 /********************************************************************************************
01036 >   BOOL HideScan::HideItems::Do(SGNameItem* pItem)
01037 
01038     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01039     Created:    27/5/99
01040     Inputs:     pItem       ---     the set item to test membership of
01041     Purpose:    Hides Wix ObjectName attributes that are applied to nodes within the
01042                 given set item.
01043     SeeAlso:    OpDeleteNames
01044 ********************************************************************************************/
01045 
01046 BOOL HideScan::HideItems::Do(SGNameItem* pItem)
01047 {
01048     // If the node is a member of the item's set then exclude it from the set.
01049     if (pItem->IsMember(m_pNode))
01050     {
01051         // Find the exact Wix attribute that makes the node a member of pItem's set.
01052         TemplateAttribute* pAttr;
01053         for (pAttr = (TemplateAttribute*) m_pNode->FindFirstAttr( &Node::IsAnObjectName );
01054              pAttr != 0;
01055              pAttr = (TemplateAttribute*) pAttr->FindNextAttr( &Node::IsAnObjectName ))
01056                 if (pItem->IsEqual(pAttr->GetParam())) break;
01057 
01058         // Try to hide the attribute.
01059         ERROR3IF(pAttr == 0, "HideScan::HideItems::Do: can't find TemplateAttribute");
01060         if (!m_pOp->DoHideNode(pAttr, TRUE, 0, TRUE)) return FALSE;
01061     }
01062 
01063     // Continue scanning items.
01064     return TRUE;
01065 }
01066 
01067 
01068 
01069 /********************************************************************************************
01070 >   HidePropScan::HidePropScan(UndoableOperation* pOp)
01071 
01072     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01073     Created:    27/5/99
01074     Inputs:     pOp     ---     the UndoableOperation that is the context for this
01075                                 scanning
01076     Purpose:    Constructs a HidePropScan object, which hides set properties for names
01077                 highlighted in the Attribute gallery.
01078     SeeAlso:    UndoableNodeScan; OpDeleteNames; HidePropScan::HideProp
01079 ********************************************************************************************/
01080 
01081 HidePropScan::HidePropScan(UndoableOperation* pOp)
01082   : HideScan(pOp, &theSetSentinel)
01083 {
01084     // Empty.
01085 }
01086 
01087 
01088 
01089 /********************************************************************************************
01090 >   virtual BOOL HidePropScan::Do(Node* pNode)
01091 
01092     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01093     Created:    27/5/99
01094     Inputs:     pNode       ---     the document's NodeSetSentinel.
01095     Purpose:    Excludes the given node from any highlighted sets in the Name Gallery.
01096     SeeAlso:    OpDeleteNames; HidePropScan::HideProp
01097 ********************************************************************************************/
01098 
01099 BOOL HidePropScan::Do(Node* pNode)
01100 {
01101     // If the object is a highlighted member of a "used names" set then hide its
01102     // properties.
01103     return HideProp(pNode, m_pOp).ForEach() == 0;
01104 }
01105 
01106 
01107 
01108 /********************************************************************************************
01109 >   HidePropScan::HideProp::HideProp(Node* pNode, UndoableOperation* pOp)
01110 
01111     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01112     Created:    27/5/99
01113     Inputs:     pNode       ---     the document's NodeSetSentinel.
01114                 pOp         --      the Operation context in which to manipulate the attrs.
01115     Purpose:    Excludes the given node from any highlighted sets in the Name Gallery.
01116     SeeAlso:    OpDeleteNames
01117 ********************************************************************************************/
01118 
01119 HidePropScan::HideProp::HideProp(Node* pNode, UndoableOperation* pOp)
01120   : HideScan::HideItems(pNode, pOp)
01121 {
01122     ERROR3IF(pNode == 0 || !pNode->IS_KIND_OF(NodeSetSentinel),
01123                 "HidePropScan::HideProp::HideProp: not a NodeSetSentinel");
01124 }
01125 
01126 
01127 
01128 /********************************************************************************************
01129 >   BOOL HidePropScan::HideProp::Do(SGNameItem* pItem)
01130 
01131     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01132     Created:    27/5/99
01133     Inputs:     pItem       ---     the set item to test membership of
01134     Purpose:    Hides set properties for all given item in the Attribute gallery.
01135     SeeAlso:    OpDeleteNames
01136 ********************************************************************************************/
01137 
01138 BOOL HidePropScan::HideProp::Do(SGNameItem* pItem)
01139 {
01140     // If the node is a member of the item's set then hide its associated property node.
01141     if (pItem->IsMember(m_pNode))
01142     {
01143         // Find the property.
01144         String_256 strName;
01145         pItem->GetNameText(&strName);
01146         NodeSetProperty* pPropNode =
01147                 Document::GetSelected()->GetSetSentinel()->FindPropertyNode(strName);
01148 
01149         // Try to hide the attribute.
01150         //ERROR3IF(pPropNode == 0, "HidePropScan::HideProp::Do: can't find NodeSetProperty");
01151         if (!pPropNode) return TRUE; // trying to delete something that isn't there! Surely we have already succeeded!
01152         if (!m_pOp->DoHideNode(pPropNode, TRUE, 0, TRUE)) return FALSE;
01153     }
01154 
01155     // Continue scanning items.
01156     return TRUE;
01157 }
01158 
01159 
01160 
01161 /********************************************************************************************
01162 >   HideSingleScan::HideSingleScan(UndoableOperation* pOp, NodeScan::Source* ps,
01163                                    const StringBase& strName)
01164     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01165     Created:    27/5/99
01166     Inputs:     pOp         ---     the UndoableOperation that is the context for this
01167                                     scanning
01168                 ps          ---     the source for candidate nodes to scan over
01169                 strName     ---     the object name to hide
01170     Purpose:    Constructs a HideSingleScan object, which hides set properties for names
01171                 highlighted in the Attribute gallery.
01172     SeeAlso:    UndoableNodeScan; HideSingleScan::Do; OpChangeSetProperties::DoWithParam
01173 ********************************************************************************************/
01174 
01175 HideSingleScan::HideSingleScan(UndoableOperation* pOp, NodeScan::Source* ps,
01176                                const StringBase& strName)
01177   : HideScan(pOp, ps),
01178     m_strName(strName),
01179     m_pUsedNames(NameGallery::Instance()->GetUsedNames())
01180 {
01181     ERROR3IF(m_pUsedNames == 0, "HideSingleScan::HideSingleScan: no used names");
01182 }
01183 
01184 
01185 
01186 /********************************************************************************************
01187 >   virtual BOOL HideSingleScan::Do(Node* pNode)
01188 
01189     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01190     Created:    27/5/99
01191     Inputs:     pNode       ---     the node to consider hiding.
01192     Purpose:    Excludes the given node from a specified set if it's a member.
01193     SeeAlso:    HideSingleScan::HideSingleScan; SGUsedNames::IsMember
01194 ********************************************************************************************/
01195 
01196 BOOL HideSingleScan::Do(Node* pNode)
01197 {
01198     // If the node is a member of the set then hide it's attribute.
01199     if (m_pUsedNames->IsMember(pNode, m_strName))
01200     {
01201         // Find the exact Wix attribute that makes the node a member of the set.
01202         TemplateAttribute* pAttr;
01203         for (pAttr = (TemplateAttribute*) pNode->FindFirstAttr( &Node::IsAnObjectName );
01204              pAttr != 0;
01205              pAttr = (TemplateAttribute*) pAttr->FindNextAttr( &Node::IsAnObjectName ))
01206                 if (pAttr->GetParam() == m_strName) break;
01207 
01208         // Try to hide the attribute.
01209         ERROR3IF(pAttr == 0, "HideSingleScan::Do: can't find TemplateAttribute");
01210         if (!m_pOp->DoHideNode(pAttr, TRUE, 0, TRUE)) return FALSE;
01211     }
01212 
01213     // Continue scanning items.
01214     return TRUE;
01215 }
01216 
01217 
01218 /********************************************************************************************
01219 >   CreateDisplayScan::CreateDisplayScan()
01220 
01221     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01222     Created:    27/5/99
01223     Purpose:    Constructs a CreateDisplayScan object.
01224     SeeAlso:    NodeScan
01225 ********************************************************************************************/
01226 
01227 CreateDisplayScan::CreateDisplayScan()
01228   : NodeScan(&theSelectedDocument)
01229 {
01230     // Empty.
01231 }
01232 
01233 
01234 
01235 /********************************************************************************************
01236 >   virtual BOOL CreateDisplayScan::Pre()
01237 
01238     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01239     Created:    27/5/99
01240     Purpose:    Called by CreateDisplayScan when the gallery display is (re)created.  Resets
01241                 the running counters of total and selected objects in each display item.
01242     SeeAlso:    NodeScan
01243 ********************************************************************************************/
01244 
01245 BOOL CreateDisplayScan::Pre()
01246 {
01247     return ClearCounters().ForEach() == 0;
01248 }
01249 
01250 
01251 
01252 /********************************************************************************************
01253 >   virtual BOOL CreateDisplayScan::Do(Node* pNode)
01254 
01255     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01256     Created:    27/5/99
01257     Inputs:     pNode           ---     the current node in the scan
01258     Purpose:    Called by CreateDisplayScan when the gallery display is (re)created.  Tests
01259                 the given node for membership of each set and if it is a member, creates
01260                 a new SGNameItem for its name ('attribute value') if one doesn't already
01261                 exist, and includes it in the running counts of total and selected objects.
01262     SeeAlso:    NodeScan
01263 ********************************************************************************************/
01264 
01265 BOOL CreateDisplayScan::Do(Node* pNode)
01266 {
01267     // Create/register with the sets that contain pInkNode as a member.
01268     return CreateItems(pNode).ForEach() == 0;
01269 }
01270 
01271 
01272 
01273 /********************************************************************************************
01274 >   virtual BOOL CreateDisplayScan::Post()
01275 
01276     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01277     Created:    27/5/99
01278     Purpose:    Called by CreateDisplayScan when the gallery display is (re)created.  Deletes
01279                 any SGNameItems which don't have any members and folds any groups that
01280                 don't have items.
01281     SeeAlso:    NodeScan
01282 ********************************************************************************************/
01283 
01284 BOOL CreateDisplayScan::Post()
01285 {
01286     return DelItemIfUnref().ForEach() == 0 && FoldGroupIfEmpty().ForEach() == 0;
01287 }
01288 
01289 
01290 
01291 /********************************************************************************************
01292 >   virtual BOOL CreateDisplayScan::ClearCounters::Do(SGNameItem* pItem)
01293 
01294     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01295     Created:    27/5/99
01296     Inputs:     pItem       ---     current item in the iteration
01297     Purpose:    Resets (zeroes) the total and selected counters in all items.
01298     SeeAlso:    CreateDisplayScan; NameItemIter
01299 ********************************************************************************************/
01300 
01301 BOOL CreateDisplayScan::ClearCounters::Do(SGNameItem* pItem)
01302 {
01303     pItem->Reset();
01304     return TRUE;
01305 }
01306 
01307 
01308 
01309 /********************************************************************************************
01310 >   CreateDisplayScan::CreateItems::CreateItems(Node* pNode)
01311 
01312     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01313     Created:    27/5/99
01314     Inputs:     pNode   ---     the node to pass to the Do function
01315     Purpose:    Constructs a CreateDisplayScan::CreateItems object.
01316     SeeAlso:    CreateDisplayScan; NameGroupIter
01317 ********************************************************************************************/
01318 
01319 CreateDisplayScan::CreateItems::CreateItems(Node* pNode)
01320   : m_pNode(pNode)
01321 {
01322     // Empty.
01323 }
01324 
01325 
01326 
01327 /********************************************************************************************
01328 >   virtual BOOL CreateDisplayScan::CreateItems::Do(SGNameGroup* pGroup)
01329 
01330     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01331     Created:    27/5/99
01332     Inputs:     pGroup      ---     current group in the iteration
01333     Purpose:    Creates items for all the sets in pGroup.
01334     SeeAlso:    CreateDisplayScan; NameItemIter
01335 ********************************************************************************************/
01336 
01337 BOOL CreateDisplayScan::CreateItems::Do(SGNameGroup* pGroup)
01338 {
01339     return pGroup->CreateItems(m_pNode);
01340 }
01341 
01342 
01343 
01344 /********************************************************************************************
01345 >   virtual BOOL CreateDisplayScan::DelItemIfNoRef::Do(SGNameItem* pItem)
01346 
01347     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01348     Created:    27/5/99
01349     Inputs:     pItem       ---     current item in the iteration
01350     Purpose:    Deletes the names of items which no longer refer to any objects.
01351 ********************************************************************************************/
01352 
01353 BOOL CreateDisplayScan::DelItemIfUnref::Do(SGNameItem* pItem)
01354 {
01355     // Basic integrity checks for the number of objects & nodes encountered.
01356     ERROR3IF(pItem->GetNodeCount() < pItem->GetObjectCount(),
01357                 "CreateDisplayScan::DelItemIfNoRef::Do: nodes < objects");
01358     ERROR3IF(pItem->GetNodeCount() > pItem->GetObjectCount() + 1,
01359                 "CreateDisplayScan::DelItemIfNoRef::Do: nodes > objects + 1");
01360     ERROR3IF(pItem->GetSelectedCount() > pItem->GetObjectCount(),
01361                 "CreateDisplayScan::DelItemIfNoRef::Do: selected > objects");
01362 
01363     // Does the item's set not contain any objects?
01364     if (pItem->GetNodeCount() == 0)
01365     {
01366         pItem->RemoveFromTree();
01367         delete pItem;
01368     }
01369 
01370     // 'Decimate the contentless 'til the bitter end', sayeth Tiberius.
01371     return TRUE;
01372 }
01373 
01374 
01375 
01376 /********************************************************************************************
01377 >   virtual BOOL CreateDisplayScan::FoldGroupIfEmpty::Do(SGNameGroup* pGroup)
01378 
01379     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01380     Created:    27/5/99
01381     Inputs:     pGroup      ---     current group in the iteration
01382     Purpose:    Folds groups which have no items.
01383 ********************************************************************************************/
01384 
01385 BOOL CreateDisplayScan::FoldGroupIfEmpty::Do(SGNameGroup* pGroup)
01386 {
01387     // Is the group item-less and unfolded?
01388     if (pGroup->GetChild() == 0 && !pGroup->Flags.Folded)
01389     {
01390         // Remember to unfold this group as soon as it has items again.  But if the user
01391         // has folded the group deliberately then we don't interfere with it.
01392         pGroup->Flags.Reserved |= 1;
01393         pGroup->Flags.Folded = TRUE;
01394     }
01395 
01396     return TRUE;
01397 }

Generated on Sat Nov 10 03:45:52 2007 for Camelot by  doxygen 1.4.4