filltool.cpp

Go to the documentation of this file.
00001 // $Id: filltool.cpp 1730 2006-09-03 10:58:17Z 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 // The Graduated Fill Tool
00099 
00100 // This is a random comment inserted just to change the size of the file
00101 // so that Will might have more luck checking it out.
00102 
00103 // includes
00104 #include "camtypes.h"
00105 
00106 #include "colourix.h"
00107 #include "csrstack.h"
00108 #include "osrndrgn.h"
00109 //#include "viewrc.h"
00110 #include "blobs.h"
00111 //#include "will.h"
00112 //#include "markn.h"
00113 //#include "rikdlg.h"
00114 #include "oilfiles.h"
00115 
00116 #include "filltool.h"
00117 #include "opgrad.h"
00118 #include "toollist.h"
00119 //#include "resource.h"
00120 
00121 #include "bitmpinf.h"
00122 //#include "wbitmap.h"
00123 #include "ophist.h"
00124 #include "keypress.h"
00125 #include "opnudge.h"
00126 #include "fillndge.h"
00127 
00128 //#include "justin2.h"
00129 //#include "will2.h"
00130 #include "bmpcomp.h"    // BitmapListComponent
00131 #include "bubbleid.h"
00132 
00133 //#include "gerry.h"        // new fill type strings (only things in the file)
00134 //#include "biasres.h"
00135 #include "nodeshad.h"
00136 //#include "grptrans.h"
00137 #include "objchge.h"
00138 #include "layer.h"
00139 //#include "simon.h"
00140 #include "opliveeffects.h"
00141 #include "effects_stack.h"
00142 #include "nodeliveeffect.h"
00143 
00144 // Revision Number
00145 DECLARE_SOURCE( "$Revision: 1730 $" );
00146 
00147 // The Names of the tools
00148 TCHAR*      GradFillTool::FamilyName = _T("Fill Tools");
00149 TCHAR*      GradFillTool::ToolName = _T("Graduated Fill Tool");
00150 TCHAR*      GradFillTool::Purpose = _T("Graduated Filling of Objects");
00151 TCHAR*      GradFillTool::Author = _T("Will");
00152 
00153 TCHAR*      TranspTool::FamilyName = _T("Fill Tools");
00154 TCHAR*      TranspTool::ToolName = _T("Transparency Tool");
00155 TCHAR*      TranspTool::Purpose = _T("Alter the transparency of objects");
00156 TCHAR*      TranspTool::Author = _T("Will");
00157 
00158 INT32 GradInfoBarOp::CurrentGeometryIndex;
00159 INT32 GradInfoBarOp::CurrentMappingIndex;
00160 INT32 GradInfoBarOp::CurrentEffectIndex;
00161 
00162 INT32 TranspInfoBarOp::CurrentGeometryIndex;
00163 INT32 TranspInfoBarOp::CurrentTransTypeIndex;
00164 INT32 TranspInfoBarOp::CurrentMappingIndex;
00165 INT32 TranspInfoBarOp::CurrentTypeIndex;
00166 INT32 TranspInfoBarOp::CurrentBitmapIndex;
00167 
00168 GradInfoBarOp* GradFillTool::pGradInfoBarOp;
00169 TranspInfoBarOp* GradFillTool::pTranspInfoBarOp;
00170 
00171 UINT32 GradFillTool::LastStatusID;
00172 BOOL GradFillTool::CurrentTool;
00173 
00174 TranspInfoBarOp* TranspTool::pTranspInfoBarOp;
00175 
00176 UINT32 TranspTool::LastStatusID;
00177 BOOL TranspTool::CurrentTool;
00178 
00179 BOOL GradFillTool::AllowFillNudges = TRUE;
00180 
00181 BOOL GradFillTool::NudgeFills = FALSE;
00182 BOOL TranspTool::NudgeFills = FALSE;
00183 
00184 static INT32 TempGeometryIndex = -1;
00185 
00186 CC_IMPLEMENT_MEMDUMP( GradFillTool, Tool_v1 )
00187 CC_IMPLEMENT_MEMDUMP( TranspTool, Tool_v1 )
00188 CC_IMPLEMENT_DYNCREATE( GradInfoBarOp,   InformationBarOp )
00189 CC_IMPLEMENT_DYNCREATE( TranspInfoBarOp,   InformationBarOp )
00190 
00191 CC_IMPLEMENT_DYNCREATE( AttrRemoveTransp,  AttrTranspChange )
00192 CC_IMPLEMENT_DYNCREATE( AttrRemoveStrokeTransp,  AttrValueChange )
00193 CC_IMPLEMENT_DYNCREATE( AttrMakeFlatTransp,  AttrTranspChange )
00194 
00195 CC_IMPLEMENT_DYNCREATE( FillProfileOpParam, OpParam)
00196 CC_IMPLEMENT_DYNCREATE( OpChangeFillProfile, SelOperation)
00197 CC_IMPLEMENT_DYNCREATE( ChangeFillProfileAction, Action)
00198 CC_IMPLEMENT_DYNCREATE( TranspFillProfileOpParam, OpParam)
00199 CC_IMPLEMENT_DYNCREATE( OpChangeTranspFillProfile, SelOperation)
00200 CC_IMPLEMENT_DYNCREATE( ChangeTranspFillProfileAction, Action)
00201 
00202 
00203 #define new CAM_DEBUG_NEW
00204 
00205 /********************************************************************************************
00206 
00207     Preference: DoFillMeshCheck
00208     Section:    DebugFlags
00209     Range:      TRUE or FALSE
00210     Purpose:    Enables or disables the check for Similar Fill meshes overwriting each other.
00211 
00212 ********************************************************************************************/
00213 
00214 
00215 
00218 
00219 //          Implementation of class FillTools
00220 
00223 
00224 
00225 
00226 /********************************************************************************************
00227 
00228 >   BOOL FillTools::BuildListOfSelectedNodes(List *pList,
00229                                              const CCRuntimeClass * pClass,
00230                                              BOOL bPromoteToParents = TRUE)
00231 
00232     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
00233     Created:    9/2/2000
00234     Inputs:     
00235     Purpose:    Builds a list of all given attribute nodes in the selection
00236 
00237 ********************************************************************************************/
00238 
00239 /*BOOL FillTools::bScanForTransparency = FALSE;
00240 
00241 BOOL FillTools::BuildListOfSelectedNodes(List *pList,
00242                                          const CCRuntimeClass* pClass,
00243                                          BOOL bPromoteToParents)
00244 {
00245     if (!pList)
00246         return FALSE;
00247 
00248     if (pClass == (CC_RUNTIME_CLASS (AttrFillGeometry)))
00249     {
00250         bScanForTransparency = FALSE;
00251     }
00252     else if (pClass == (CC_RUNTIME_CLASS (AttrTranspFillGeometry)))
00253     {
00254         bScanForTransparency = TRUE;
00255     }
00256     else
00257     {
00258         ERROR3("Someone's forgotten to read my notes about this function!");
00259         return (FALSE);
00260     }
00261     
00262     // run through the selection adding all nodes to the list
00263     Range Sel(*(GetApplication()->FindSelection()));
00264     RangeControl rg = Sel.GetRangeControlFlags();
00265     rg.PromoteToParent = bPromoteToParents;
00266     Sel.Range::SetRangeControl(rg);
00267 
00268     if (Sel.IsEmpty())
00269         return FALSE;
00270 
00271     Node * pNode = Sel.FindFirst(FALSE);
00272 
00273     NodeListItem * pItem = NULL;
00274 
00275     while (pNode)
00276     {
00277         GetAllNodesUnderNode(pNode, pList, pClass);
00278 
00279         pNode = Sel.FindNext(pNode, FALSE);
00280     }
00281 
00282     if (pList->IsEmpty())
00283         return FALSE;
00284 
00285     return TRUE;
00286 }
00287 */
00288 
00289 
00290 
00291 // It's important that all parts of Camelot find attributes in the same ways - otherwise
00292 // the UI might be showing one set of things and the code changing a completely different
00293 // set!
00294 //
00295 // This function uses the applied attr functions to determine which attributes are in
00296 // scope in the selection instead of assuming that all attrs under the selected node
00297 // are relevant...
00298 //
00299 /*BOOL FillTools::BuildListOfSelectedAttrs(List* pList,
00300                                          const CCRuntimeClass* pClass,
00301                                          BOOL bPromoteToParents)
00302 {
00303     ERROR3IF(pList==NULL, "BuildListOfAttrs called with no list");
00304     if (!pList)
00305         return FALSE;
00306 
00307     // run through the selection adding all nodes to the list
00308     Range Sel(*(GetApplication()->FindSelection()));
00309     RangeControl rg = Sel.GetRangeControlFlags();
00310     rg.PromoteToParent = bPromoteToParents;
00311     Sel.Range::SetRangeControl(rg);
00312 
00313     if (Sel.IsEmpty())
00314         return FALSE;
00315 
00316     Node* pNode = Sel.FindFirst();
00317     NodeListItem* pItem = NULL;
00318 
00319     while (pNode)
00320     {
00321         if (pNode->IsAnObject())
00322         {
00323             NodeAttribute* pAttr = ((NodeRenderableInk*)pNode)->FindAppliedAttribute((CCRuntimeClass*)pClass);
00324             if (pAttr && !pAttr->IsADefaultAttr())
00325             {
00326                 pItem = new NodeListItem;
00327                 if (pItem)
00328                 {
00329                     pItem->pNode = pAttr;
00330                     pList->AddTail(pItem);
00331                 }
00332                 else
00333                 {
00334                     pList->DeleteAll();
00335                     break;
00336                 }
00337             }
00338         }
00339 
00340         pNode = Sel.FindNext(pNode);
00341     }
00342 
00343     if (pList->IsEmpty())
00344         return FALSE;
00345 
00346     return TRUE;
00347 }
00348 */
00349 
00350 
00351 
00352 /********************************************************************************************
00353 
00354 >   BOOL FillTools::GetAllNodesUnderNode(const Node * pNode, List * pList,
00355                                          const CCRuntimeClass * pClass, INT32 depth = 0)
00356 
00357     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
00358     Created:    9/2/2000
00359     Inputs:     The node to recurse down from, and the list to add found attributes to
00360     Purpose:    Recurses down the tree building a list of all light attribute nodes
00361 
00362 ********************************************************************************************/
00363 
00364 /*BOOL FillTools::GetAllNodesUnderNode(const Node * pNode, List * pList,
00365                                      const CCRuntimeClass * pClass, INT32 depth)
00366 {
00367     if (!pNode || !pList)
00368         return FALSE;
00369 
00370     const Node * pStartNode = pNode;
00371 
00372     // NOTHING exists under a locked (destructive) effect!
00373     if (pNode->IsBitmapEffect() && ((NodeBitmapEffect*)pNode)->IsLockedEffect())
00374         return TRUE;
00375 
00376     Node * pCurNode = pNode->FindFirstChild();
00377 
00378     Node * pChild = NULL;
00379     NodeListItem * pItem = NULL;
00380 
00381     if (!pCurNode)
00382     {
00383         // starting conditions
00384         if (pStartNode->IsKindOf(CC_RUNTIME_CLASS(AttrFillGeometry)) &&
00385             depth == 0 &&
00386             IsNodeTrueFill(pStartNode) &&
00387             !IsNodeInList(pList, pStartNode)
00388             )
00389         {
00390             pItem = new NodeListItem;
00391 
00392             if (pItem)
00393             {
00394                 pItem->pNode = (Node *)pStartNode;
00395                 pList->AddTail(pItem);
00396 
00397                 return TRUE;
00398             }
00399         }
00400 
00401         return FALSE;
00402     }
00403     
00404     // step through the node's siblings
00405     while (pCurNode)
00406     {   
00407         // check sub-tree first
00408         GetAllNodesUnderNode(pCurNode, pList, pClass, depth + 1);
00409         
00410         // check this node is of the correct class, and it also has a parent
00411         if (pCurNode->IsKindOf(CC_RUNTIME_CLASS (AttrFillGeometry)) && IsNodeTrueFill (pCurNode) && pCurNode->FindParent() &&
00412             !pCurNode->IsNodeHidden() && !IsNodeInList(pList, pCurNode))
00413         {
00414             pItem = new NodeListItem;
00415 
00416             if (!pItem)
00417             {
00418                 ERROR3("Can't create NodeListItem");
00419                 return FALSE;
00420             }
00421 
00422             pItem->pNode = pCurNode;
00423             pList->AddTail(pItem);
00424         }
00425 
00426         // move onto next sibling
00427         pCurNode = pCurNode->FindNext();
00428     }
00429 
00430     // check original node
00431     if (pStartNode->IsKindOf(CC_RUNTIME_CLASS(AttrFillGeometry)) &&
00432         IsNodeTrueFill(pStartNode) &&
00433         pStartNode->FindParent() &&
00434         !pStartNode->IsNodeHidden() &&
00435         !IsNodeInList(pList, pStartNode)
00436         )
00437     {
00438         pItem = new NodeListItem;
00439 
00440         if (!pItem)
00441         {
00442             ERROR3("Can't create NodeListItem");
00443             return FALSE;
00444         }
00445 
00446         pItem->pNode = (Node *)pStartNode;
00447         pList->AddTail(pItem);
00448     }
00449 
00450     return TRUE;
00451 }
00452 */
00453 
00454 
00455 /********************************************************************************************
00456 
00457 >   BOOL FillTools::IsNodeInList(List * pList, Node * pNode)
00458 
00459     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
00460     Created:    9/2/2000
00461     Inputs:     A list of NodeListItems and the node to search for
00462     Purpose:    Returns TRUE if the node is in the list
00463 
00464 ********************************************************************************************/
00465 
00466 BOOL FillTools::IsNodeInList(List * pList, const Node * pNode)
00467 {
00468     NodeListItem * pItem = (NodeListItem * )pList->GetHead();
00469 
00470     while (pItem)
00471     {
00472         if (pItem->pNode == pNode)
00473             return TRUE;
00474 
00475         pItem = (NodeListItem * )pList->GetNext(pItem);
00476     }
00477 
00478     return FALSE;
00479 }
00480 
00481 
00482 
00483 /********************************************************************************************
00484 
00485 >   BOOL FillTools::IsNodeTrueFill (const Node * pNode)
00486 
00487     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
00488     Created:    9/2/2000
00489     Inputs:     A ptr to the current node
00490     Purpose:    Returns TRUE if the node is a gradient fill
00491 
00492 ********************************************************************************************/
00493 
00494 /*BOOL FillTools::IsNodeTrueFill (const Node * pNode)
00495 {
00496     if (bScanForTransparency == FALSE)
00497     {
00498         if ((((AttrFillGeometry*) pNode)->IsAGradFill ()) && (!(((AttrFillGeometry*) pNode)->IsATranspFill ())))
00499         {
00500             return (TRUE);
00501         }
00502         else
00503         {
00504             return (FALSE);
00505         }
00506     }
00507     else //(bScanForTransparency == TRUE)
00508     {
00509         if ((((AttrFillGeometry*) pNode)->IsAGradFill ()) && (((AttrFillGeometry*) pNode)->IsATranspFill ()))
00510         {
00511             return (TRUE);
00512         }
00513         else
00514         {
00515             return (FALSE);
00516         }
00517     }
00518 }
00519 */
00520 
00521 BOOL FillTools::GetSelectedAttrList(List* pList,
00522                                     const CCRuntimeClass* pClass,
00523                                     BOOL bGradFill,
00524                                     BOOL bTranspFill,
00525                                     EffectsStack* pUseThisStack)
00526 {
00527     ERROR2IF(pList==NULL, FALSE, "GetSelectedAttrList passed NULL list pointer");
00528     ERROR2IF(pClass==NULL, FALSE, "GetSelectedAttrList passed NULL class pointer");
00529 
00530     EffectsStack* pStack = NULL;
00531 
00532     if (pUseThisStack != NULL)
00533         pStack = pUseThisStack;
00534     else
00535         pStack = GetApplication()->FindSelection()->GetEffectsStack();  // From cache
00536 
00537     ENSURE(pStack, "Can't find PostProStack");
00538 
00539     INT32 iStackPos = STACKPOS_TOP;
00540     Range* pLevelRange = pStack->GetLevelRange(&iStackPos, FALSE);      // Don't escape old controllers when scanning for attributes
00541     if (pLevelRange == NULL)
00542         return FALSE;
00543 
00544     Node* pNode = pLevelRange->FindFirst();
00545     while (pNode)
00546     {
00547         if (pNode->IsAnObject())
00548         {
00549             NodeAttribute* pAttr = ((NodeRenderableInk*)pNode)->FindAppliedAttribute((CCRuntimeClass*)pClass);
00550             if (pAttr && !pAttr->IsADefaultAttr() && pAttr->IsAGradFill()==bGradFill && pAttr->IsATranspFill()==bTranspFill)
00551             {
00552                 NodeListItem * pItem = new NodeListItem;
00553                 if (pItem)
00554                 {
00555                     pItem->pNode = pAttr;
00556                     pList->AddTail(pItem);
00557                 }
00558                 else
00559                 {
00560                     pList->DeleteAll();
00561                     return FALSE;
00562                 }
00563             }
00564         }
00565 
00566         pNode = pLevelRange->FindNext(pNode);
00567     }
00568 
00569     return TRUE;
00570 }
00571 
00572 
00575 
00576 //          Implementation of class GradFillTool (graduated fill tool)
00577 
00580 
00581 
00582 
00583 /********************************************************************************************
00584 
00585 >   GradFillTool::GradFillTool()
00586 
00587     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00588     Created:    19/7/94
00589     Purpose:    Constructs a Fill Tool.
00590 
00591 ********************************************************************************************/
00592 
00593 GradFillTool::GradFillTool()
00594 {
00595     ClickStart = DocCoord(0,0);
00596     IsSelection = FALSE;
00597     StartSpread = NULL;
00598     pGradFillCursor = NULL;
00599     CurrentCursorID = 0;
00600 
00601     NudgeFills = FALSE;
00602 }
00603 
00604 /********************************************************************************************
00605 
00606 >   GradFillTool::~GradFillTool()
00607 
00608     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00609     Created:    19/7/94
00610     Purpose:    Destructor. Does nothing.
00611 
00612 ********************************************************************************************/
00613 
00614 GradFillTool::~GradFillTool()
00615 {
00616     // Dummy destructor
00617 }
00618 
00619 /********************************************************************************************
00620 
00621 >   BOOL GradFillTool::Init()
00622 
00623     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00624     Created:    19/7/94
00625     Returns:    FALSE if it does not want to be created, TRUE otherwise
00626     Purpose:    Used to check if the Tool was properly constructed
00627     SeeAlso:    GradFillTool::GradFillTool
00628 
00629 ********************************************************************************************/
00630 
00631 BOOL GradFillTool::Init()
00632 {
00633     BOOL ok = TRUE;
00634 
00635     ok = OpChangeFillProfile::Declare();
00636 
00637 #if 0
00638     if (ok)
00639     {
00640         // Is everything ok so far ?
00641         CCResTextFile       file;               // Resource File
00642         GradInfoBarOpCreate BarCreate;          // Object that creates GradInfoBarOp objects
00643 
00644                 ok = file.open(_R(IDM_GRAD_BAR), _R(IDT_INFO_BAR_RES));     // Open resource
00645         if (ok) ok = DialogBarOp::ReadBarsFromFile(file,BarCreate); // Read and create info bar
00646         if (ok) file.close();                                       // Close resource
00647 
00648         ENSURE(ok,"Unable to load gradbar.ini from resource\n"); 
00649         String_32 str = String_32(_R(IDS_FILLTOOL_FILLINFOBARNAME));
00650         DialogBarOp* pDialogBarOp = DialogBarOp::FindDialogBarOp(str);
00651     }
00652 #endif
00653 
00654     if (ok)
00655     {
00656         // Info bar now exists.  Now get a pointer to it
00657         pGradInfoBarOp = new GradInfoBarOp(_R(IDD_GRADFILLDLG));
00658 
00659         if (pGradInfoBarOp)
00660         {
00661             // Set our default menu items
00662             pGradInfoBarOp->CurrentGeometryIndex = FGMENU_LINEAR;
00663             pGradInfoBarOp->CurrentMappingIndex = FMMENU_SIMPLE;
00664             pGradInfoBarOp->CurrentEffectIndex = FEMENU_FADE;
00665         } else
00666             ok=FALSE;
00667 
00668         ENSURE(ok,"Couldn't find grad tool info bar");
00669     }
00670 
00671     return (ok);
00672 }
00673 
00674 /********************************************************************************************
00675 
00676 >   void GradFillTool::Describe(void *InfoPtr)
00677 
00678     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00679     Created:    19/7/94
00680     Inputs:     InfoPtr - A pointer to a tool info block. It is passed cast to void* as
00681                 the version of the tool is unknown at this point. Later versions of the
00682                 Tool class may have more items in this block, that this tool will not use
00683     Outputs:    InfoPtr - The structure pointed to by InfoPtr will have had all the info
00684                 that this version of the Tool knows about
00685     Purpose:    Allows the tool manager to extract information about the tool
00686 
00687 ********************************************************************************************/
00688 
00689 void GradFillTool::Describe(void *InfoPtr)
00690 {
00691     // Cast structure into the latest one we understand.
00692     ToolInfo_v1 *Info = (ToolInfo_v1 *) InfoPtr;
00693 
00694     Info -> InfoVersion = 1;
00695     
00696     Info -> InterfaceVersion = GetToolInterfaceVersion();  // You should always have this line.
00697         
00698     // These are all arbitrary at present.
00699     Info -> Version = 1;
00700     Info -> ID      = GetID();
00701     Info -> TextID   = _R(IDS_GRADFILL_TOOL);
00702     Info -> BubbleID = _R(IDBBL_FILL_TOOL);
00703 
00704     Info -> Family  = FamilyName;
00705     Info -> Name    = ToolName;
00706     Info -> Purpose = Purpose;
00707     Info -> Author  = Author;
00708 
00709     Info -> InfoBarDialog = 0;
00710 }
00711 
00712 // The EventHandlers
00713 
00714 /********************************************************************************************
00715 
00716 >   virtual void GradFillTool::SelectChange(BOOL isSelected)
00717 
00718     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00719     Created:    19/07/94
00720     Inputs:     -
00721     Outputs:    -
00722     Returns:    -
00723     Purpose:    Creates/destroys/pushes/pops the rectangle tool's cursor.
00724     Errors:     Debug warning if creating the cursor fails.
00725     SeeAlso:    -
00726 
00727 ********************************************************************************************/
00728 
00729 void GradFillTool::SelectChange(BOOL isSelected)
00730 {
00731     if (isSelected)
00732     {
00733         // This tool has just been selected.  Create an appropriate cursor, in this case
00734         // we can use the operating system-provided crosshair cursor.
00735         pGradFillCursor  = new Cursor(this, _R(IDC_GRADTOOLCURSOR));
00736         pGradPointCursor = new Cursor(this, _R(IDC_GRADPOINTCURSOR));
00737 
00738         // Did the cursor create ok ?
00739         if (!pGradFillCursor || !pGradFillCursor->IsValid())
00740         {
00741             return;
00742         }
00743 
00744         // Did the cursor create ok ?
00745         if (!pGradPointCursor || !pGradPointCursor->IsValid())
00746         {
00747             return;
00748         }
00749 
00750         pCurrentCursor = pGradFillCursor;
00751         CurrentCursorID = CursorStack::GPush(pGradFillCursor, FALSE);   // Push cursor, but don't display now
00752 
00753         // Create and display the tool's info bar
00754         CurrentTool = TRUE;
00755         AttrFillGeometry::SetTranspMeshesVisible(FALSE);
00756 
00757         // Which blobs do I want displayed
00758         BlobManager* BlobMgr = GetApplication()->GetBlobManager();
00759         if (BlobMgr != NULL)
00760         {
00761             // Decide which blobs to display
00762             BlobStyle MyBlobs;
00763             MyBlobs.Tiny = TRUE;
00764             MyBlobs.Fill = TRUE;
00765 
00766             // tell the blob manager
00767             BlobMgr->ToolInterest(MyBlobs);
00768         }
00769 
00770         // Re-Count the number of selected fill control points
00771         AttrFillGeometry::SetSelectionCount(AttrFillGeometry::CountSelectionControlPoints());
00772 
00773         pGradInfoBarOp->Create();
00774         pGradInfoBarOp->EnableControls ();
00775 
00776         if (AttrFillGeometry::SelectionCount > 0)
00777             EnableFillNudge();
00778 
00779         TempGeometryIndex = -1;
00780         //CurrentGeometryIndex = ;
00781 
00782         SelRange *Selected = GetApplication()->FindSelection();
00783 
00784         // There is a selection if there is a document, and it has some selected object(s)
00785         IsSelection = (Document::GetCurrent() != NULL && Selected->Count() > 0);
00786 
00787         if (IsSelection)
00788         {
00789             SelectionBox  = Selected->GetBoundingRect();
00790 
00791             Node* Current = Selected->FindFirst();
00792             if (Current != NULL)
00793             {
00794                 Spread *pSpread = Current->FindParentSpread();
00795                 RenderToolBlobs(pSpread, NULL);
00796             }
00797         }
00798     }
00799     else
00800     {
00801 //      pGradInfoBarOp->ResetHiddenGadgetStates ();
00802         
00803         DisableFillNudge();
00804 
00805         // Deselection - destroy the tool's cursor, if there is one.
00806         if (pGradFillCursor)
00807         {
00808             CursorStack::GPop(CurrentCursorID);
00809             delete pGradFillCursor;
00810             delete pGradPointCursor;
00811 
00812             pCurrentCursor = NULL;
00813             CurrentCursorID = 0;
00814         }
00815 
00816         pGradInfoBarOp->CloseProfileDialog (pGradInfoBarOp->m_BiasGainGadget);
00817 
00818         pGradInfoBarOp->Delete();
00819 
00820         CurrentTool = FALSE;
00821 
00822         // If needed, draw the [tool blobs? OK, who forgot to finish the comment?!]
00823         if (IsSelection && Document::GetCurrent()!=NULL)
00824         {
00825             SelRange *Selected = GetApplication()->FindSelection();
00826             Node *Current = Selected->FindFirst();
00827 
00828             if (Current!=NULL)
00829             {
00830                 Spread *pSpread = Current->FindParentSpread();
00831                 RenderToolBlobs(pSpread, NULL);
00832             }
00833         }
00834 
00835         // ensure any tool object blobs are removed.
00836         BlobManager* BlobMgr = GetApplication()->GetBlobManager();
00837         if (BlobMgr != NULL)
00838         {
00839             BlobStyle bsRemoves;
00840             bsRemoves.ToolObject = TRUE;
00841             BlobMgr->RemoveInterest(bsRemoves);
00842         }
00843     }
00844 }
00845 
00846 /********************************************************************************************
00847 
00848 >   void GradFillTool::OnClick( DocCoord PointerPos, ClickType Click, ClickModifiers ClickMods,
00849                         Spread* pSpread )
00850 
00851 
00852     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00853     Created:    19/7/94
00854     Inputs:     PointerPos - The Coords (in DocCoords) of the point where the mouse button
00855                 was clicked
00856                 Click - Describes the type of click that was detected. 
00857                 ClickMods - Indicates which buttons caused the click and which modifers were
00858                 pressed at the same time
00859     Returns:    TRUE if it handled the Click, FALSE otherwise
00860     Purpose:    To handle a Mouse Click event for the Selector Tool. It starts up a Selector 
00861                 Operation.
00862     SeeAlso:    Tool::MouseClick; ClickType; ClickModifiers
00863 
00864 ********************************************************************************************/
00865 
00866 void GradFillTool::OnClick( DocCoord PointerPos, ClickType Click, ClickModifiers ClickMods,
00867                         Spread* pSpread )
00868 {
00869     if (ClickMods.Menu) return;                         // Don't do anything if the user clicked the Menu button
00870 
00871     // See if there is already a drag going on
00872     if (Operation::GetCurrentDragOp()!=NULL)
00873         return;
00874 
00875     if ( AttrFillGeometry::CheckAttrClick(PointerPos, Click, ClickMods, pSpread) )
00876     {
00877         // nastiness ALERT !!!!!
00878 
00879         // since we can now double click to insert a multi-stage fill blob, we also MUST
00880         // select that blob once it is created.  ONLY problem is that we cannot do this
00881         // (since it dosen't exist) UNTIL we have redrawn the screen ....
00882         
00883         if ( Click == CLICKTYPE_DOUBLE )
00884         {
00885             SelRange *Selected = GetApplication()->FindSelection();
00886             Node *Current = Selected->FindFirst();
00887 
00888             if (Current!=NULL)
00889             {
00890                 Spread *pSpread2 = Current->FindParentSpread();
00891                 RenderToolBlobs(pSpread2, NULL);
00892                 
00893                 // the only sensible way to select the new blob is to fake a mouse click on it ....
00894                 
00895                 AttrFillGeometry::CheckAttrClick(PointerPos, CLICKTYPE_SINGLE, ClickMods, pSpread2);
00896 
00897                 // now fake an onmousemove to get our cursor/status line to change as well!
00898                 
00899                 OnMouseMove (PointerPos, pSpread, ClickMods);
00900             }
00901         }
00902         
00903         return;     // An Attribute claimed the click
00904     }
00905 
00906     // Make sure this click is one that we want
00907     if ( Click == CLICKTYPE_SINGLE )
00908     {
00909         StartPos = PointerPos;
00910         StartSpread = pSpread;
00911         DoubleClicked = FALSE;
00912     }
00913 
00914     if ( Click == CLICKTYPE_UP )
00915     {
00916         StartPos = DocCoord(0,0);
00917         StartSpread = NULL;
00918         DoubleClicked = FALSE;
00919     }
00920 
00921     if ( Click == CLICKTYPE_DOUBLE )
00922     {
00923         DoubleClicked = TRUE;       
00924     }
00925 
00926     if ( Click == CLICKTYPE_DRAG )
00927     {
00928         if (StartSpread == NULL)
00929             return;
00930 
00931         // Just what we wanted - Someone is dragging the mouse about
00932         // We need to make an operation to perform the drag with
00933 //      OpCreateFill* pOp = new OpCreateFill;
00934         OpEditFill* pOp = new OpEditFill;
00935         if (pOp == NULL)
00936         {
00937             // Inform the person doing the clicking that life is not looking so good
00938             InformError();
00939         }
00940         else
00941         {
00942             AttrFillGeometry* Fill = NULL;
00943             // Start the drag operation and pass in the Anchor Point to the push operation
00944 
00945             if (ClickMods.Adjust)
00946             {
00947                 Fill = new AttrRadialColourFill;
00948                 if (Fill != NULL)
00949                     ((AttrRadialFill*)Fill)->MakeCircular();
00950             }
00951 #ifndef WEBSTER
00952             else if (DoubleClicked)
00953             {
00954                 Fill = new AttrConicalColourFill;
00955             }
00956 #endif //WEBSTER
00957             else
00958             {
00959                 switch (pGradInfoBarOp->CurrentGeometryIndex)
00960                 {
00961                     case (FGMENU_FLAT):
00962                         // DMc changed - for the multiple colour fills
00963                         Fill = new AttrLinearColourFill;
00964                         break;
00965 
00966                     case (FGMENU_LINEAR):
00967                         Fill = new AttrLinearColourFill;
00968                         break;
00969 
00970                     case (FGMENU_CIRCULAR):
00971                         Fill = new AttrRadialColourFill;
00972                         if (Fill != NULL)
00973                             ((AttrRadialFill*)Fill)->MakeCircular();
00974                         break;
00975 
00976                     case (FGMENU_RADIAL):
00977                         Fill = new AttrRadialColourFill;
00978                         break;
00979 
00980                     case (FGMENU_CONICAL):
00981                         Fill = new AttrConicalColourFill;
00982                         break;
00983 
00984                     case (FGMENU_SQUARE):
00985                         Fill = new AttrSquareColourFill;
00986                         break;
00987 
00988                     case (FGMENU_THREECOL):
00989                         Fill = new AttrThreeColColourFill;
00990                         break;
00991 
00992                     case (FGMENU_FOURCOL):
00993                         Fill = new AttrFourColColourFill;
00994                         break;
00995 
00996                     case (FGMENU_BITMAP):
00997                         Fill = new AttrBitmapColourFill;
00998 
00999                         Fill->AttachBitmap(NULL);
01000                         Fill->SetTesselation(pGradInfoBarOp->CurrentMappingIndex+1);
01001                         break;
01002 
01003                     case (FGMENU_FRACTAL):
01004                         Fill = new AttrFractalColourFill;
01005                         Fill->SetTesselation(pGradInfoBarOp->CurrentMappingIndex+1);
01006                         break;
01007 
01008                     case (FGMENU_NOISE):
01009                         Fill = new AttrNoiseColourFill;
01010                         Fill->SetTesselation(pGradInfoBarOp->CurrentMappingIndex+1);
01011                         break;
01012 
01013                     default:
01014                         // Er .. Dunno what kind of fill this is ?
01015                         Fill = new AttrLinearColourFill;
01016                         break;
01017                 }
01018             }
01019     
01020             if (Fill == NULL)
01021             {
01022                 InformError();
01023                 return;
01024             }
01025 
01026             pOp->DoCreate(StartPos, StartSpread, Fill);
01027         }
01028 
01029         StartPos = DocCoord(0,0);
01030         StartSpread = NULL;
01031         DoubleClicked = FALSE;
01032         return;
01033     }
01034 
01035     // call the base class ....
01036 
01037     DragTool::OnClick (PointerPos, Click, ClickMods, pSpread);
01038 }
01039 
01040 /********************************************************************************************
01041 
01042 >   void GradFillTool::OnMouseMove(DocCoord Pos, Spread* pSpread, ClickModifiers ClickMods)
01043 
01044     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01045     Created:    19/07/94
01046     Inputs:     Pos - The current position of the mouse.
01047                 pSpread - The current spread.
01048     Purpose:    Called whenever the mouse position changes.
01049                 We use this to update the cursor and status messages.
01050 
01051 ********************************************************************************************/
01052 
01053 void GradFillTool::OnMouseMove(DocCoord Pos, Spread* pSpread, ClickModifiers ClickMods)
01054 {
01055     // Setup defaults
01056     Cursor* pCursor = pGradFillCursor;
01057     String_256 Status;
01058 
01059     if (ClickMods.Adjust)
01060         TempGeometryIndex = FGMENU_CIRCULAR;
01061     else
01062         TempGeometryIndex = -1;
01063 
01064     GetCursorAndStatus(Pos, pSpread, &pCursor, &Status);
01065 
01066     if (pCursor != pCurrentCursor)
01067     {
01068         // We're using the wrong shape!! 
01069         pCurrentCursor = pCursor;
01070         CursorStack::GSetTop(pCurrentCursor, CurrentCursorID);
01071     }
01072         
01073     // Display the status text
01074     GetApplication()->UpdateStatusBarText(&Status);
01075 }
01076 
01077 /********************************************************************************************
01078 
01079 >   BOOL GradFillTool::OnKeyPress(KeyPress* pKeyPress)
01080 
01081     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01082     Created:    29/3/94
01083     Inputs:     pKeyPress = Ptr to a platform-indy key press object
01084     Outputs:    -
01085     Returns:    TRUE  - the key press was processed, so do NOT pass on
01086                 FALSE - not processed, so let others have a bash
01087     Purpose:    Checks for fill tool keys.
01088     Errors:     -
01089                                                                  
01090 ********************************************************************************************/
01091 
01092 BOOL GradFillTool::OnKeyPress(KeyPress* pKeyPress)
01093 {
01094     if (pKeyPress->GetVirtKey() == CAMKEY(TAB) &&
01095         !pKeyPress->IsRelease() &&
01096         !pKeyPress->IsRepeat())
01097     {
01098         // Toggle the selection state of all visible fill control points
01099         ToggleControlPoints(pKeyPress->IsAdjust());
01100 
01101         return TRUE;
01102     }
01103 
01104     if ( IsFillNudgeEnabled() &&
01105         (pKeyPress->GetVirtKey() == CAMKEY(UP) ||
01106          pKeyPress->GetVirtKey() == CAMKEY(DOWN) ||
01107          pKeyPress->GetVirtKey() == CAMKEY(LEFT) ||
01108          pKeyPress->GetVirtKey() == CAMKEY(RIGHT)) )
01109     {
01110         // If we are nudging, then stop the Attribute manager from sending
01111         // tons of messages, until the nudge stops.
01112         if (pKeyPress->IsRelease())
01113             AttributeManager::SendMessages = TRUE;
01114         else
01115             AttributeManager::SendMessages = FALSE;
01116 
01117         // Pass on the nudge keys
01118         return FALSE;
01119     }
01120     return FALSE;
01121 }
01122 
01123 /********************************************************************************************
01124 
01125 >   void GradFillTool::ToggleControlPoints(BOOL Reverse)
01126 
01127     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01128     Created:    29/3/94
01129     Inputs:     Reverse - if true the points will cycle in the opposite direction
01130     Purpose:    Toggles the selection state of all visible fill control blobs.
01131                                                                  
01132 ********************************************************************************************/
01133 
01134 void GradFillTool::ToggleControlPoints(BOOL Reverse)
01135 {
01136     // Switch control points
01137     AttrFillGeometry::LastRenderedStartBlob = DocCoord(0,0);
01138     AttrFillGeometry::LastRenderedEndBlob = DocCoord(0,0);
01139     AttrFillGeometry::LastRenderedEnd2Blob = DocCoord(0,0);
01140     AttrFillGeometry::LastRenderedEnd3Blob = DocCoord(0,0);
01141 
01142     AttrFillGeometry* pAttrNode = AttrFillGeometry::FindFirstSelectedAttr();
01143 
01144     // Return if there aren't any
01145     if (pAttrNode == NULL)
01146         return;
01147 
01148     // We only toggle if there are some points selected
01149     BOOL DoToggle = AttrFillGeometry::FillSelectionCount() > 0;
01150 
01151     while (pAttrNode != NULL)
01152     {
01153         if (pAttrNode->IsAColourFill())
01154         {
01155             if (DoToggle)
01156             {
01157                 // We're going to toggle the selected control points.
01158                 if (pAttrNode->GetSelectionCount() > 0)
01159                 {
01160                     pAttrNode->CycleSelection(Reverse);
01161                 }
01162             }
01163             else
01164             {
01165                 // There were no points selected, so we'll just
01166                 // select all the start points.
01167                 pAttrNode->SelectBlob(FILLCONTROL_STARTPOINT);
01168             }
01169         }
01170 
01171         // Check the next fill
01172         pAttrNode = AttrFillGeometry::FindNextSelectedAttr();
01173     }
01174 
01175     BROADCAST_TO_ALL(SelChangingMsg(SelChangingMsg::COLOURATTCHANGED)); 
01176 }
01177 
01178 /********************************************************************************************
01179 
01180 >   void GradFillTool::EnableFillNudge()
01181 
01182     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01183     Created:    29/3/94
01184     Purpose:    Enables the fill control point nudging.
01185     Errors:     -
01186                                                                  
01187 ********************************************************************************************/
01188 
01189 void GradFillTool::EnableFillNudge()
01190 {
01191     if (!GradFillTool::AllowFillNudges || NudgeFills)
01192         return;
01193     
01194     //Alias all the nudge ops to the fill specific ones.
01195     OpFillNudge::NudgeColours(TRUE);
01196     
01197     OpDescriptor* pOpDesc;
01198 
01199     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEUP1) ;
01200     if (pOpDesc) pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeUp1),NULL,0);
01201     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEUP5);  
01202     if (pOpDesc) pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeUp5),NULL,0);  
01203     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEUP10);  
01204     if (pOpDesc) pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeUp10),NULL,0);  
01205     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEUPFIFTH);
01206     if (pOpDesc) pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeUpFifth),NULL,0);
01207     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEUPPIXEL1);
01208     if (pOpDesc) pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeUpPixel1),NULL,0);
01209     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEUPPIXEL10);
01210     if (pOpDesc) pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeUpPixel10),NULL,0);
01211 
01212     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEDOWN1);  
01213     if (pOpDesc) pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeDown1),NULL,0);  
01214     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEDOWN5);  
01215     if (pOpDesc) pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeDown5),NULL,0);  
01216     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEDOWN10);  
01217     if (pOpDesc) pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeDown10),NULL,0);  
01218     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEDOWNFIFTH);
01219     if (pOpDesc) pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeDownFifth),NULL,0);
01220     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEDOWNPIXEL1);
01221     if (pOpDesc) pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeDownPixel1),NULL,0);
01222     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEDOWNPIXEL10);
01223     if (pOpDesc) pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeDownPixel10),NULL,0);
01224 
01225     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGELEFT1);  
01226     if (pOpDesc) pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeLeft1),NULL,0);  
01227     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGELEFT5);  
01228     if (pOpDesc) pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeLeft5),NULL,0);  
01229     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGELEFT10);  
01230     if (pOpDesc) pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeLeft10),NULL,0);  
01231     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGELEFTFIFTH);
01232     if (pOpDesc) pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeLeftFifth),NULL,0);
01233     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGELEFTPIXEL1);
01234     if (pOpDesc) pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeLeftPixel1),NULL,0);
01235     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGELEFTPIXEL10);
01236     if (pOpDesc) pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeLeftPixel10),NULL,0);
01237 
01238     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGERIGHT1);  
01239     if (pOpDesc) pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeRight1),NULL,0);  
01240     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGERIGHT5);  
01241     if (pOpDesc) pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeRight5),NULL,0);  
01242     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGERIGHT10);  
01243     if (pOpDesc) pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeRight10),NULL,0);  
01244     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGERIGHTFIFTH);
01245     if (pOpDesc) pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeRightFifth),NULL,0);
01246     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGERIGHTPIXEL1);
01247     if (pOpDesc) pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeRightPixel1),NULL,0);
01248     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGERIGHTPIXEL10);
01249     if (pOpDesc) pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeRightPixel10),NULL,0);
01250     
01251     NudgeFills = TRUE;
01252 }
01253 
01254 /********************************************************************************************
01255 
01256 >   void GradFillTool::DisableFillNudge()
01257 
01258     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01259     Created:    29/3/94
01260     Purpose:    Disables the fill control point nudging.
01261     Errors:     -
01262                                                                  
01263 ********************************************************************************************/
01264 
01265 void GradFillTool::DisableFillNudge()
01266 {
01267     if (!GradFillTool::AllowFillNudges || !NudgeFills)
01268         return;
01269 
01270     NudgeFills = FALSE;
01271 
01272     //Un-alias all the nudge ops back like they were.
01273     
01274     OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEUP1);  
01275     pOpDesc->RemoveAlias();  
01276     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEUP5);  
01277     pOpDesc->RemoveAlias();  
01278     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEUP10);  
01279     pOpDesc->RemoveAlias();  
01280     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEUPFIFTH);
01281     pOpDesc->RemoveAlias();
01282     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEUPPIXEL1);
01283     pOpDesc->RemoveAlias();
01284     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEUPPIXEL10);
01285     pOpDesc->RemoveAlias();
01286 
01287     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEDOWN1);  
01288     pOpDesc->RemoveAlias();  
01289     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEDOWN5);  
01290     pOpDesc->RemoveAlias();  
01291     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEDOWN10);  
01292     pOpDesc->RemoveAlias();  
01293     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEDOWNFIFTH);
01294     pOpDesc->RemoveAlias();
01295     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEDOWNPIXEL1);
01296     pOpDesc->RemoveAlias();
01297     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEDOWNPIXEL10);
01298     pOpDesc->RemoveAlias();
01299 
01300     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGELEFT1);  
01301     pOpDesc->RemoveAlias();  
01302     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGELEFT5);  
01303     pOpDesc->RemoveAlias();  
01304     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGELEFT10);  
01305     pOpDesc->RemoveAlias();  
01306     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGELEFTFIFTH);
01307     pOpDesc->RemoveAlias();
01308     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGELEFTPIXEL1);
01309     pOpDesc->RemoveAlias();
01310     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGELEFTPIXEL10);
01311     pOpDesc->RemoveAlias();
01312 
01313 
01314     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGERIGHT1);  
01315     pOpDesc->RemoveAlias();  
01316     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGERIGHT5);  
01317     pOpDesc->RemoveAlias();  
01318     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGERIGHT10);  
01319     pOpDesc->RemoveAlias();  
01320     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGERIGHTFIFTH);
01321     pOpDesc->RemoveAlias();
01322     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGERIGHTPIXEL1);
01323     pOpDesc->RemoveAlias();
01324     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGERIGHTPIXEL10);
01325     pOpDesc->RemoveAlias();
01326 }
01327 
01328 /********************************************************************************************
01329 
01330 >   BOOL GradFillTool::IsFillNudgeEnabled()
01331 
01332     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01333     Created:    29/3/94
01334     Returns:    TRUE  - Fill nudging is disabled
01335                 FALSE - Fill nudging is enabled
01336     Purpose:    Checks for to see if the fill nudging is currently enabled or not.
01337     Errors:     -
01338                                                                  
01339 ********************************************************************************************/
01340 
01341 BOOL GradFillTool::IsFillNudgeEnabled()
01342 {
01343     return NudgeFills;
01344 }
01345 
01346 /*****************************************************************************
01347 
01348 >   virtual BOOL GradFillTool::GetStatusLineText(String_256* ptext, Spread* pSpread,
01349                                                  DocCoord DocPos, ClickModifiers ClickMods);
01350 
01351     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01352     Created:    9/12/94
01353     Inputs:     pSpread   - pointer to spread under mouse (else NULL)
01354                 DocPos    - position of mouse in doc (in spread coords)
01355                 ClickMods - mouse click modifiers
01356     Outputs:    ptext - text for status line
01357     Returns:    TRUE if outputting valid text
01358     Purpose:    generate up-to-date text for the status line (called on idles)
01359 
01360 *****************************************************************************/
01361 
01362 BOOL GradFillTool::GetStatusLineText(String_256* ptext, Spread* pSpread, 
01363                                      DocCoord DocPos, ClickModifiers ClickMods)
01364 {
01365     ERROR3IF(ptext==NULL,"GradFillTool::GetStatusLineText() - ptext passed as null");
01366 
01367     if (ClickMods.Adjust)
01368         TempGeometryIndex = FGMENU_CIRCULAR;
01369     else
01370         TempGeometryIndex = -1;
01371 
01372     GetCursorAndStatus(DocPos, pSpread, NULL, ptext);
01373 
01374     return TRUE;
01375 }
01376 
01377 /********************************************************************************************
01378 
01379 >   void GradFillTool::GetCursorAndStatus(DocCoord Pos, Spread* pSpread, 
01380                                           Cursor** pCursor, String_256* pStatus)
01381     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01382     Created:    9/12/94
01383     Inputs:     Pos - The current position of the mouse.
01384     Purpose:    Get the correct cursor and status message for this mouse position.
01385 
01386 ********************************************************************************************/
01387 
01388 void GradFillTool::GetCursorAndStatus(DocCoord Pos, Spread* pSpread, 
01389                                       Cursor** pCursor, String_256* pStatus)
01390 {
01391     // Setup defaults
01392     UINT32 Status;
01393     Cursor* pNewCursor = pGradFillCursor;
01394 
01395     AttrFillGeometry::DoCheckOnFillRampMesh = FALSE;        // disable this feature
01396 
01397     // Is the mouse over any of our fill control points ?
01398     if ( AttrFillGeometry::CheckForFillControlHit(Pos, &Status) )
01399     {
01400         // Status will have been updated
01401 
01402         // Change the cursor, to indicate the mouse is over a control point
01403         pNewCursor = pGradPointCursor;
01404     }
01405     else
01406     {
01407         INT32 Index = pGradInfoBarOp->CurrentGeometryIndex;
01408 
01409         if (TempGeometryIndex != -1)
01410             Index = TempGeometryIndex;
01411 
01412         // Check our menu status
01413         switch (Index)
01414         {      
01415             // If fill controls are selected then we indicate 
01416             // that a click will deselect them.
01417             // Otherwise we just show what kind of fill will
01418             // be created when the user drags.
01419 
01420             case (FGMENU_FLAT):
01421                 if ( AttrFillGeometry::FillSelectionCount() > 0 )
01422                     Status = _R(IDS_FS_CREATELINEAR_S);     
01423                 else                                    
01424                     Status = _R(IDS_FS_CREATELINEAR);
01425                 break;
01426 
01427             case (FGMENU_LINEAR):
01428                 if ( AttrFillGeometry::FillSelectionCount() > 0 )
01429                     Status = _R(IDS_FS_CREATELINEAR_S);     
01430                 else                                    
01431                     Status = _R(IDS_FS_CREATELINEAR);
01432                 break;
01433 
01434             case (FGMENU_CIRCULAR):
01435                 if ( AttrFillGeometry::FillSelectionCount() > 0 )
01436                     Status = _R(IDS_FS_CREATECIRCLE_S);
01437                 else
01438                     Status = _R(IDS_FS_CREATECIRCLE);
01439                 break;
01440 
01441             case (FGMENU_RADIAL):
01442                 if ( AttrFillGeometry::FillSelectionCount() > 0 )
01443                     Status = _R(IDS_FS_CREATEELLIP_S);
01444                 else
01445                     Status = _R(IDS_FS_CREATEELLIP);
01446                 break;
01447 
01448             case (FGMENU_CONICAL):
01449                 if ( AttrFillGeometry::FillSelectionCount() > 0 )
01450                     Status = _R(IDS_FS_CREATECONICAL_S);
01451                 else
01452                     Status = _R(IDS_FS_CREATECONICAL);
01453                 break;
01454 
01455             case (FGMENU_SQUARE):
01456                 if ( AttrFillGeometry::FillSelectionCount() > 0 )
01457                     Status = _R(IDS_FS_CREATESQUARE_S);
01458                 else
01459                     Status = _R(IDS_FS_CREATESQUARE);
01460                 break;
01461 
01462             case (FGMENU_THREECOL):
01463                 if ( AttrFillGeometry::FillSelectionCount() > 0 )
01464                     Status = _R(IDS_FS_CREATETHREECOL_S);
01465                 else
01466                     Status = _R(IDS_FS_CREATETHREECOL);
01467                 break;
01468 
01469             case (FGMENU_FOURCOL):
01470                 if ( AttrFillGeometry::FillSelectionCount() > 0 )
01471                     Status = _R(IDS_FS_CREATEFOURCOL_S);
01472                 else
01473                     Status = _R(IDS_FS_CREATEFOURCOL);
01474                 break;
01475 
01476             case (FGMENU_BITMAP):
01477                 if ( AttrFillGeometry::FillSelectionCount() > 0 )
01478                     Status = _R(IDS_FS_CREATEBITMAP_S);
01479                 else
01480                     Status = _R(IDS_FS_CREATEBITMAP);
01481                 break;
01482 
01483             case (FGMENU_FRACTAL):
01484                 if ( AttrFillGeometry::FillSelectionCount() > 0 )
01485                     Status = _R(IDS_FS_CREATEFRACTAL_S);
01486                 else
01487                     Status = _R(IDS_FS_CREATEFRACTAL);
01488                 break;
01489 
01490             case (FGMENU_NOISE):
01491                 if ( AttrFillGeometry::FillSelectionCount() > 0 )
01492                     Status = _R(IDS_FS_CREATENOISE_S);
01493                 else
01494                     Status = _R(IDS_FS_CREATENOISE);
01495                 break;
01496 
01497             default:
01498                 // Er .. Dunno what kind of fill this is ?
01499                 Status = _R(IDS_FS_CREATELINEAR);
01500                 break;
01501         }
01502     }
01503 
01504     if (pStatus != NULL)
01505     {
01506         pStatus->Load(Status);
01507         LastStatusID = Status;
01508     }
01509 
01510     if (pCursor != NULL)
01511         *pCursor = pNewCursor;
01512 
01513     AttrFillGeometry::DoCheckOnFillRampMesh = TRUE;         // enable again
01514 }
01515 
01516 /********************************************************************************************
01517 
01518 >   static void GradTool::DisplayStatusBarHelp(UINT32 StatusID)
01519 
01520     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01521     Created:    9/8/94
01522     Inputs:     StatusID = ID of status help string
01523     Outputs:    -
01524     Returns:    -
01525     Purpose:    Displays the given status help string in the status bar
01526     SeeAlso:    -
01527 
01528 ********************************************************************************************/
01529 
01530 void GradFillTool::DisplayStatusBarHelp(UINT32 StatusID)
01531 {
01532     String_256 StatusMsg("");
01533     StatusMsg.Load(StatusID);
01534     GetApplication()->UpdateStatusBarText(&StatusMsg);
01535     LastStatusID = StatusID;
01536 }
01537 
01538 
01539 
01542 
01543 //          Implementation of class TranspTool (Transparency Tool)
01544 
01547 
01548 
01549 
01550 /********************************************************************************************
01551 
01552 >   TranspTool::TranspTool()
01553 
01554     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01555     Created:    3/10/94
01556     Purpose:    Constructs a Transparency Tool.
01557 
01558 ********************************************************************************************/
01559 
01560 TranspTool::TranspTool()
01561 {
01562     ClickStart = DocCoord(0,0);
01563     IsSelection = FALSE;
01564     StartSpread = NULL;
01565     pTranspCursor = NULL;
01566     CurrentCursorID = 0;
01567 
01568     CurrentTool = FALSE;
01569     NudgeFills = FALSE;
01570 }
01571 
01572 /********************************************************************************************
01573 
01574 >   TranspTool::~TranspTool()
01575 
01576     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01577     Created:    3/10/94
01578     Purpose:    Destructor. Does nothing.
01579 
01580 ********************************************************************************************/
01581 
01582 TranspTool::~TranspTool()
01583 {
01584     // Dummy destructor
01585 }
01586 
01587 /********************************************************************************************
01588 
01589 >   BOOL TranspTool::Init()
01590 
01591     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01592     Created:    3/10/94
01593     Returns:    FALSE if it does not want to be created, TRUE otherwise
01594     Purpose:    Used to check if the Tool was properly constructed
01595     SeeAlso:    TranspTool::TranspTool
01596 
01597 ********************************************************************************************/
01598 
01599 BOOL TranspTool::Init()
01600 {
01601     BOOL ok = TRUE;
01602 
01603     ok = OpChangeTranspFillProfile::Declare();
01604 
01605 #if 0
01606     if (ok)
01607     {
01608         CCResTextFile       file;               // Resource File
01609         TranspInfoBarOpCreate BarCreate;        // Object that creates TranspInfoBarOp objects
01610 
01611                 ok = file.open(_R(IDM_TRANSP_BAR), _R(IDT_INFO_BAR_RES));       // Open resource
01612         if (ok) ok = DialogBarOp::ReadBarsFromFile(file,BarCreate); // Read and create info bar
01613         if (ok) file.close();                                       // Close resource
01614 
01615         ENSURE(ok,"Unable to load transbar.ini from resource\n"); 
01616 
01617         // Info bar now exists.  Now get a pointer to it
01618         String_32 str = String_32(_R(IDS_FILLTOOL_TRANINFOBARNAME));
01619         DialogBarOp* pDialogBarOp = DialogBarOp::FindDialogBarOp(str);
01620 
01621     }
01622 #endif
01623     if (ok)
01624     {
01625         pTranspInfoBarOp = new TranspInfoBarOp(_R(IDD_TRANFILLDLG));
01626 
01627         if (pTranspInfoBarOp)
01628         {
01629             // Set our default menu items
01630             pTranspInfoBarOp->CurrentGeometryIndex = FGMENU_LINEARTRANSP;
01631             pTranspInfoBarOp->CurrentMappingIndex = FMMENU_SIMPLE;
01632             pTranspInfoBarOp->CurrentTypeIndex = FTMENU_REFLECT;
01633         } else
01634             ok=FALSE;
01635 
01636         ENSURE(ok,"Unable to load transbar.ini from resource\n"); 
01637 
01638     }
01639 
01640     return (ok);
01641 }
01642 
01643 /********************************************************************************************
01644 
01645 >   void TranspTool::Describe(void *InfoPtr)
01646 
01647     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01648     Created:    19/7/94
01649     Inputs:     InfoPtr - A pointer to a tool info block. It is passed cast to void* as
01650                 the version of the tool is unknown at this point. Later versions of the
01651                 Tool class may have more items in this block, that this tool will not use
01652     Outputs:    InfoPtr - The structure pointed to by InfoPtr will have had all the info
01653                 that this version of the Tool knows about
01654     Purpose:    Allows the tool manager to extract information about the tool
01655 
01656 ********************************************************************************************/
01657 
01658 void TranspTool::Describe(void *InfoPtr)
01659 {
01660     // Cast structure into the latest one we understand.
01661     ToolInfo_v1 *Info = (ToolInfo_v1 *) InfoPtr;
01662 
01663     Info -> InfoVersion = 1;
01664     
01665     Info -> InterfaceVersion = GetToolInterfaceVersion();  // You should always have this line.
01666         
01667     // These are all arbitrary at present.
01668     Info -> Version = 1;
01669     Info -> ID      = GetID();
01670     Info -> TextID   = _R(IDS_TRANSP_TOOL);
01671     Info -> BubbleID = _R(IDBBL_TRANSP_TOOL);
01672 
01673     Info -> Family  = FamilyName;
01674     Info -> Name    = ToolName;
01675     Info -> Purpose = Purpose;
01676     Info -> Author  = Author;
01677 
01678     Info -> InfoBarDialog = 0;
01679 }
01680 
01681 // The EventHandlers
01682 
01683 /********************************************************************************************
01684 
01685 >   virtual void TranspTool::SelectChange(BOOL isSelected)
01686 
01687     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01688     Created:    19/07/94
01689     Inputs:     -
01690     Outputs:    -
01691     Returns:    -
01692     Purpose:    Creates/destroys/pushes/pops the rectangle tool's cursor.
01693     Errors:     Debug warning if creating the cursor fails.
01694     SeeAlso:    -
01695 
01696 ********************************************************************************************/
01697 
01698 void TranspTool::SelectChange(BOOL isSelected)
01699 {
01700     if (isSelected)
01701     {
01702         // This tool has just been selected.  Create an appropriate cursor, in this case
01703         // we can use the operating system-provided crosshair cursor.
01704         pTranspCursor  = new Cursor(this, _R(IDC_TRANSPTOOLCURSOR));
01705         pTranspPointCursor = new Cursor(this, _R(IDC_TRANSPPOINTCURSOR));
01706 
01707         // Did the cursor create ok ?
01708         if (!pTranspCursor || !pTranspCursor->IsValid())
01709         {
01710             return;
01711         }
01712 
01713         // Did the cursor create ok ?
01714         if (!pTranspPointCursor || !pTranspPointCursor->IsValid())
01715         {
01716             return;
01717         }
01718 
01719         pCurrentCursor = pTranspCursor;
01720         CurrentCursorID = CursorStack::GPush(pTranspCursor, FALSE); // Push cursor, but don't display now
01721 
01722         // Create and display the tool's info bar
01723         CurrentTool = FALSE;
01724         AttrFillGeometry::SetTranspMeshesVisible(FALSE);
01725 
01726         BlobManager* BlobMgr = GetApplication()->GetBlobManager();
01727 
01728         BlobStyle MyBlobs = BlobMgr->GetCurrentInterest();
01729         if (MyBlobs.Fill)
01730         {
01731             MyBlobs.Fill = FALSE;
01732             MyBlobs.Effect = FALSE;
01733             BlobMgr->ToolInterest(MyBlobs);
01734         }
01735 
01736         CurrentTool = TRUE;
01737         AttrFillGeometry::SetTranspMeshesVisible(TRUE);
01738 
01739         SelRange *Selected = GetApplication()->FindSelection();
01740 
01741         BlobStyle ToolBlobs;
01742         ToolBlobs.Fill = TRUE;
01743         ToolBlobs.Tiny = TRUE;
01744         ToolBlobs.Effect = TRUE;
01745         BlobMgr->ToolInterest(ToolBlobs);
01746 
01747         // Re-Count the number of selected fill control points
01748         AttrFillGeometry::SetSelectionCount(AttrFillGeometry::CountSelectionControlPoints());
01749 
01750         pTranspInfoBarOp->Create();
01751 
01752         if (AttrFillGeometry::SelectionCount > 0)
01753             EnableFillNudge();
01754 
01755         TempGeometryIndex = -1;
01756 
01757         // There is a selection if there is a document, and it has some selected object(s)
01758         IsSelection = (Document::GetCurrent() != NULL && Selected->Count() > 0);
01759 
01760         if (IsSelection)
01761         {
01762             SelectionBox  = Selected->GetBoundingRect();
01763 
01764             Node* Current = Selected->FindFirst();
01765             if (Current != NULL)
01766             {
01767                 Spread *pSpread = Current->FindParentSpread();
01768                 RenderToolBlobs(pSpread, NULL);
01769             }
01770         }
01771     }
01772     else
01773     {
01774         DisableFillNudge();
01775 
01776         // Deselection - destroy the tool's cursor, if there is one.
01777         if (pTranspCursor)
01778         {
01779             CursorStack::GPop(CurrentCursorID);
01780             delete pTranspCursor;
01781             delete pTranspPointCursor;
01782 
01783             pCurrentCursor = NULL;
01784             CurrentCursorID = 0;
01785         }
01786 
01787         pTranspInfoBarOp->CloseProfileDialog(pTranspInfoBarOp->m_BiasGainGadget);
01788         
01789         pTranspInfoBarOp->Delete();
01790 
01791         CurrentTool = TRUE;
01792         AttrFillGeometry::SetTranspMeshesVisible(TRUE);
01793 
01794         BlobManager* BlobMgr = GetApplication()->GetBlobManager();
01795 
01796         BlobStyle MyBlobs = BlobMgr->GetCurrentInterest();
01797         MyBlobs.Fill = FALSE;
01798         MyBlobs.Effect = FALSE;
01799         BlobMgr->ToolInterest(MyBlobs);
01800 
01801         CurrentTool = FALSE;
01802         AttrFillGeometry::SetTranspMeshesVisible(FALSE);
01803 
01804         // If needed, draw the [tool blobs? OK, who forgot to finish the comment?!]
01805         if (IsSelection && Document::GetCurrent()!=NULL)
01806         {
01807             SelRange *Selected = GetApplication()->FindSelection();
01808             Node *Current = Selected->FindFirst();
01809 
01810             if (Current!=NULL)
01811             {
01812                 Spread *pSpread = Current->FindParentSpread();
01813                 RenderToolBlobs(pSpread, NULL);
01814             }
01815         }
01816 
01817         // ensure any tool object blobs are removed.
01818         BlobStyle bsRemoves;
01819         bsRemoves.ToolObject = TRUE;
01820         BlobMgr->RemoveInterest(bsRemoves);
01821     }
01822 }
01823 
01824 /********************************************************************************************
01825 
01826 >   void TranspTool::OnClick( DocCoord PointerPos, ClickType Click, ClickModifiers ClickMods,
01827                         Spread* pSpread )
01828 
01829 
01830     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01831     Created:    19/7/94
01832     Inputs:     PointerPos - The Coords (in DocCoords) of the point where the mouse button
01833                 was clicked
01834                 Click - Describes the type of click that was detected. 
01835                 ClickMods - Indicates which buttons caused the click and which modifers were
01836                 pressed at the same time
01837     Returns:    TRUE if it handled the Click, FALSE otherwise
01838     Purpose:    To handle a Mouse Click event for the Selector Tool. It starts up a Selector 
01839                 Operation.
01840     SeeAlso:    Tool::MouseClick; ClickType; ClickModifiers
01841     Note:       WEBSTER-Martin-22/11/96 disallow editting and creation of transparency types
01842                 we don't want Webster to have.
01843 
01844 ********************************************************************************************/
01845 
01846 void TranspTool::OnClick( DocCoord PointerPos, ClickType Click, ClickModifiers ClickMods,
01847                         Spread* pSpread )
01848 {
01849     if (ClickMods.Menu) return;                         // Don't do anything if the user clicked the Menu button
01850 
01851     // See if there is already a drag going on
01852     if (Operation::GetCurrentDragOp()!=NULL)
01853         return;
01854 
01855     if ( AttrFillGeometry::CheckAttrClick(PointerPos, Click, ClickMods, pSpread) )
01856     {   
01857         return;     // An Attribute claimed the click
01858     }
01859 
01860     // Make sure this click is one that we want
01861     if ( Click == CLICKTYPE_SINGLE )
01862     {
01863         StartPos = PointerPos;
01864         StartSpread = pSpread;
01865         DoubleClicked = FALSE;
01866     }
01867 
01868     // Make sure this click is one that we want
01869     if ( Click == CLICKTYPE_UP )
01870     {
01871         StartPos = DocCoord(0,0);
01872         StartSpread = NULL;
01873         DoubleClicked = FALSE;
01874     }
01875 
01876     if ( Click == CLICKTYPE_DOUBLE )
01877     {
01878         DoubleClicked = TRUE;       
01879     }
01880 
01881     if ( Click == CLICKTYPE_DRAG )
01882     {
01883         // is there a shadow node in the selection ? if so, don't start a drag
01884         // DMc - check for nodes which transparency can't be applied to
01885         BOOL allowed = TRUE;
01886 
01887         Range Sel(*(GetApplication()->FindSelection()));
01888 
01889         INT32 Count = Sel.Count();
01890         INT32 ShadCount = 0;
01891 
01892         Node * pNode = Sel.FindFirst(FALSE);
01893         
01894         while (pNode)
01895         {
01896             if (pNode->IsKindOf(CC_RUNTIME_CLASS(NodeShadow)))
01897             {
01898                 allowed = FALSE;
01899                 ((NodeShadow*)pNode)->DeSelect(TRUE);
01900                 ShadCount ++;
01901             }
01902 
01903             pNode = Sel.FindNext(pNode, FALSE);
01904         }
01905 
01906         if (!allowed && Count == ShadCount)
01907         {
01908             return;
01909         }
01910 
01911         if (!allowed)
01912         {
01913             GetApplication()->UpdateSelection();
01914         }
01915 
01916         if (StartSpread == NULL)
01917             return;
01918 
01919         // Just what we wanted - Someone is dragging the mouse about
01920         // We need to make an operation to perform the drag with
01921 //      OpCreateFill* pOp = new OpCreateFill;
01922         OpEditFill* pOp = new OpEditFill;
01923         if (pOp == NULL)
01924         {
01925             // Inform the person doing the clicking that life is not looking so good
01926             InformError();
01927         }
01928         else
01929         {
01930             AttrFillGeometry* Fill = NULL;
01931             // Start the drag operation and pass in the Anchor Point to the push operation
01932 
01933             if (ClickMods.Adjust)
01934             {
01935                 Fill = new AttrRadialTranspFill;
01936                 if (Fill != NULL)
01937                     ((AttrRadialFill*)Fill)->MakeCircular();
01938             }
01939 #ifndef WEBSTER
01940             else if (DoubleClicked)
01941             {
01942                 //this could never be executed anyway even in Camelot - MAB 20/03/97
01943                 Fill = new AttrConicalTranspFill;
01944             }
01945 #endif //WEBSTER
01946             else
01947             {
01948                 switch (pTranspInfoBarOp->CurrentGeometryIndex)
01949                 {
01950                     case (FGMENU_NOTRANSP):
01951                         Fill = new AttrLinearTranspFill;
01952                         break;
01953 
01954                     case (FGMENU_FLATTRANSP):
01955                         Fill = new AttrLinearTranspFill;
01956                         break;
01957 
01958                     case (FGMENU_LINEARTRANSP):
01959                         Fill = new AttrLinearTranspFill;
01960                         break;
01961 
01962                     case (FGMENU_CIRCULARTRANSP):
01963                         Fill = new AttrRadialTranspFill;
01964                         if (Fill != NULL)
01965                             ((AttrRadialFill*)Fill)->MakeCircular();
01966                         break;
01967 
01968                     case (FGMENU_RADIALTRANSP):
01969                         Fill = new AttrRadialTranspFill;
01970                         break;
01971 
01972                     case (FGMENU_CONICALTRANSP):
01973                         Fill = new AttrConicalTranspFill;
01974                         break;
01975 
01976                     case (FGMENU_SQUARETRANSP):
01977                         Fill = new AttrSquareTranspFill;
01978                         break;
01979 
01980                     case (FGMENU_THREECOLTRANSP):
01981                         Fill = new AttrThreeColTranspFill;
01982                         break;
01983 
01984                     case (FGMENU_FOURCOLTRANSP):
01985                         Fill = new AttrFourColTranspFill;
01986                         break;
01987 
01988                     case (FGMENU_BITMAPTRANSP):
01989                     {
01990                         Fill = new AttrBitmapTranspFill;
01991 
01992                         KernelBitmap* Default = NULL;
01993                         Default = KernelBitmap::MakeKernelBitmap();
01994                         if (Default == NULL)
01995                         {
01996                             InformError();
01997                             delete Fill;
01998                             return;
01999                         }
02000 
02001                         Fill->AttachBitmap(Default);
02002                         Fill->SetTesselation(pTranspInfoBarOp->CurrentMappingIndex+1);
02003                         break;
02004                     }
02005 
02006                     case (FGMENU_FRACTALTRANSP):
02007                         Fill = new AttrFractalTranspFill;
02008                         Fill->SetTesselation(pTranspInfoBarOp->CurrentMappingIndex+1);
02009                         break;
02010 
02011                     case (FGMENU_NOISETRANSP):
02012                         Fill = new AttrNoiseTranspFill;
02013                         Fill->SetTesselation(pTranspInfoBarOp->CurrentMappingIndex+1);
02014                         break;
02015 
02016                     default:
02017                         // Er .. Dunno what kind of fill this is ?
02018                         Fill = new AttrLinearTranspFill;
02019                         break;
02020                 }
02021             }
02022             
02023             if (Fill == NULL)
02024             {
02025                 InformError();
02026                 delete pOp;
02027                 return;
02028             }
02029 
02030             Fill->SetTranspType(pTranspInfoBarOp->GetTranspType());
02031 
02032 //          pOp->DoDrag(Fill, StartSpread, StartPos);
02033             pOp->DoCreate(StartPos, StartSpread, Fill);
02034         }
02035 
02036         StartPos = DocCoord(0,0);
02037         StartSpread = NULL;
02038         DoubleClicked = FALSE;
02039         return;
02040     }
02041 
02042     // call the base class ....
02043 
02044     DragTool::OnClick (PointerPos, Click, ClickMods, pSpread);
02045 }
02046 
02047 /********************************************************************************************
02048 
02049 >   void TranspTool::OnMouseMove(DocCoord Pos, Spread* pSpread, ClickModifiers ClickMods)
02050 
02051     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
02052     Created:    19/07/94
02053     Inputs:     Pos - The current position of the mouse.
02054                 pSpread - The current spread.
02055     Purpose:    Called whenever the mouse position changes.
02056                 We use this to update the cursor and status messages.
02057 
02058 ********************************************************************************************/
02059 
02060 void TranspTool::OnMouseMove(DocCoord Pos, Spread* pSpread, ClickModifiers ClickMods)
02061 {
02062     // Setup defaults
02063     Cursor* pCursor = pTranspCursor;
02064     String_256 Status;
02065 
02066     if (ClickMods.Adjust)
02067         TempGeometryIndex = FGMENU_CIRCULARTRANSP;
02068     else
02069         TempGeometryIndex = -1;
02070 
02071     GetCursorAndStatus(Pos, pSpread, &pCursor, &Status);
02072 
02073     if (pCursor != pCurrentCursor)
02074     {
02075         // We're using the wrong shape!! 
02076         pCurrentCursor = pCursor;
02077         CursorStack::GSetTop(pCurrentCursor, CurrentCursorID);
02078     }
02079         
02080     // Display the status text
02081     GetApplication()->UpdateStatusBarText(&Status);
02082 }
02083 
02084 /********************************************************************************************
02085 
02086 >   BOOL TranspTool::OnKeyPress(KeyPress* pKeyPress)
02087 
02088     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
02089     Created:    29/3/94
02090     Inputs:     pKeyPress = Ptr to a platform-indy key press object
02091     Outputs:    -
02092     Returns:    TRUE  - the key press was processed, so do NOT pass on
02093                 FALSE - not processed, so let others have a bash
02094     Purpose:    Checks for fill tool keys.
02095     Errors:     -
02096                                                                  
02097 ********************************************************************************************/
02098 
02099 BOOL TranspTool::OnKeyPress(KeyPress* pKeyPress)
02100 {
02101     if (pKeyPress->GetVirtKey() == CAMKEY(TAB) &&
02102         !pKeyPress->IsRelease() &&
02103         !pKeyPress->IsRepeat())
02104     {
02105         // Toggle the selection state of all visible fill control points
02106         ToggleControlPoints(pKeyPress->IsAdjust());
02107 
02108         return TRUE;
02109     }
02110 
02111     if ( IsFillNudgeEnabled() &&
02112         (pKeyPress->GetVirtKey() == CAMKEY(UP) ||
02113          pKeyPress->GetVirtKey() == CAMKEY(DOWN) ||
02114          pKeyPress->GetVirtKey() == CAMKEY(LEFT) ||
02115          pKeyPress->GetVirtKey() == CAMKEY(RIGHT)) )
02116     {
02117         // If we are nudging, then stop the Attribute manager from sending
02118         // tons of messages, until the nudge stops.
02119         if (pKeyPress->IsRelease())
02120             AttributeManager::SendMessages = TRUE;
02121         else
02122             AttributeManager::SendMessages = FALSE;
02123 
02124         // Pass on the nudge keys
02125         return FALSE;
02126     }
02127     return FALSE;
02128 }
02129 
02130 /********************************************************************************************
02131 
02132 >   void TranspTool::ToggleControlPoints(BOOL Reverse)
02133 
02134     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
02135     Created:    29/3/94
02136     Inputs:     Reverse - if TRUE the points cycle backwards
02137     Purpose:    Toggles the selection state of all visible fill control blobs.
02138     Notes:      Changed by Gerry (8/96) to use new CycleSelection call
02139 
02140 ********************************************************************************************/
02141 
02142 void TranspTool::ToggleControlPoints(BOOL Reverse)
02143 {
02144     // Switch control points
02145     AttrFillGeometry::LastRenderedStartBlob = DocCoord(0,0);
02146     AttrFillGeometry::LastRenderedEndBlob = DocCoord(0,0);
02147     AttrFillGeometry::LastRenderedEnd2Blob = DocCoord(0,0);
02148     AttrFillGeometry::LastRenderedEnd3Blob = DocCoord(0,0);
02149 
02150     AttrFillGeometry* pAttrNode = AttrFillGeometry::FindFirstSelectedAttr(CC_RUNTIME_CLASS(AttrTranspFillGeometry));
02151 
02152     // Return if there aren't any
02153     if (pAttrNode == NULL)
02154         return;
02155 
02156     // We only toggle if there are some points selected
02157     BOOL DoToggle = AttrFillGeometry::FillSelectionCount() > 0;
02158 
02159     while (pAttrNode != NULL)
02160     {
02161         if (pAttrNode->IsATranspFill())
02162         {
02163             if (DoToggle)
02164             {
02165                 // We're going to toggle the selected control points.
02166                 if (pAttrNode->GetSelectionCount() > 0)
02167                 {
02168                     pAttrNode->CycleSelection(Reverse);
02169                 }
02170             }
02171             else
02172             {
02173                 // There were no points selected, so we'll just
02174                 // select all the start points.
02175                 pAttrNode->SelectBlob(FILLCONTROL_STARTPOINT);
02176             }
02177         }
02178 
02179         // Check the next fill
02180         pAttrNode = AttrFillGeometry::FindNextSelectedAttr(CC_RUNTIME_CLASS(AttrTranspFillGeometry));
02181     }
02182 
02183     BROADCAST_TO_ALL(SelChangingMsg(SelChangingMsg::COLOURATTCHANGED)); 
02184 }
02185 
02186 /********************************************************************************************
02187 
02188 >   void TranspTool::EnableFillNudge()
02189 
02190     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
02191     Created:    29/3/94
02192     Purpose:    Enables the fill control point nudging.
02193     Errors:     -
02194                                                                  
02195 ********************************************************************************************/
02196 void TranspTool::EnableFillNudge()
02197 {
02198     if (!GradFillTool::AllowFillNudges || NudgeFills)
02199         return;
02200 
02201     //Alias all the nudge ops to the fill specific ones.
02202     OpFillNudge::NudgeColours(FALSE);
02203 
02204     OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEUP1);  
02205     pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeUp1),NULL,0);  
02206     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEUP5);  
02207     pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeUp5),NULL,0);  
02208     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEUP10);  
02209     pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeUp10),NULL,0);  
02210     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEUPFIFTH);  
02211     pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeUpFifth),NULL,0);  
02212     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEUPPIXEL1);  
02213     pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeUpPixel1),NULL,0);  
02214     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEUPPIXEL10);  
02215     pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeUpPixel10),NULL,0);  
02216 
02217     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEDOWN1);  
02218     pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeDown1),NULL,0);  
02219     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEDOWN5);  
02220     pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeDown5),NULL,0);  
02221     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEDOWN10);  
02222     pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeDown10),NULL,0);  
02223     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEDOWNFIFTH);  
02224     pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeDownFifth),NULL,0);  
02225     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEDOWNPIXEL1);  
02226     pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeDownPixel1),NULL,0);  
02227     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEDOWNPIXEL10);  
02228     pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeDownPixel10),NULL,0);  
02229 
02230     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGELEFT1);  
02231     pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeLeft1),NULL,0);  
02232     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGELEFT5);  
02233     pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeLeft5),NULL,0);  
02234     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGELEFT10);  
02235     pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeLeft10),NULL,0);  
02236     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGELEFTFIFTH);  
02237     pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeLeftFifth),NULL,0);  
02238     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGELEFTPIXEL1);  
02239     pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeLeftPixel1),NULL,0);  
02240     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGELEFTPIXEL10);  
02241     pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeLeftPixel10),NULL,0);  
02242 
02243     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGERIGHT1);  
02244     pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeRight1),NULL,0);  
02245     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGERIGHT5);  
02246     pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeRight5),NULL,0);  
02247     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGERIGHT10);  
02248     pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeRight10),NULL,0);  
02249     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGERIGHTFIFTH);  
02250     pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeRightFifth),NULL,0);  
02251     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGERIGHTPIXEL1);  
02252     pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeRightPixel1),NULL,0);  
02253     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGERIGHTPIXEL10);  
02254     pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpFillNudgeRightPixel10),NULL,0);  
02255 
02256 
02257     NudgeFills = TRUE;
02258 }
02259 
02260 /********************************************************************************************
02261 
02262 >   void TranspTool::DisableFillNudge()
02263 
02264     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
02265     Created:    29/3/94
02266     Purpose:    Disables the fill control point nudging.
02267     Errors:     -
02268                                                                  
02269 ********************************************************************************************/
02270 
02271 void TranspTool::DisableFillNudge()
02272 {
02273     if (!GradFillTool::AllowFillNudges || !NudgeFills)
02274         return;
02275 
02276     NudgeFills = FALSE;
02277 
02278     //Un-alias all the nudge ops back like they were.
02279     OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEUP1);  
02280     pOpDesc->RemoveAlias();  
02281     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEUP5);  
02282     pOpDesc->RemoveAlias();  
02283     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEUP10);  
02284     pOpDesc->RemoveAlias();  
02285     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEUPFIFTH);  
02286     pOpDesc->RemoveAlias();  
02287     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEUPPIXEL1);  
02288     pOpDesc->RemoveAlias();  
02289     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEUPPIXEL10);  
02290     pOpDesc->RemoveAlias();  
02291 
02292     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEDOWN1);  
02293     pOpDesc->RemoveAlias();  
02294     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEDOWN5);  
02295     pOpDesc->RemoveAlias();  
02296     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEDOWN10);  
02297     pOpDesc->RemoveAlias();  
02298     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEDOWNFIFTH);  
02299     pOpDesc->RemoveAlias();  
02300     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEDOWNPIXEL1);  
02301     pOpDesc->RemoveAlias();  
02302     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEDOWNPIXEL10);  
02303     pOpDesc->RemoveAlias();  
02304 
02305     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGELEFT1);  
02306     pOpDesc->RemoveAlias();  
02307     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGELEFT5);  
02308     pOpDesc->RemoveAlias();  
02309     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGELEFT10);  
02310     pOpDesc->RemoveAlias();  
02311     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGELEFTFIFTH);  
02312     pOpDesc->RemoveAlias();  
02313     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGELEFTPIXEL1);  
02314     pOpDesc->RemoveAlias();  
02315     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGELEFTPIXEL10);  
02316     pOpDesc->RemoveAlias();  
02317 
02318     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGERIGHT1);  
02319     pOpDesc->RemoveAlias();  
02320     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGERIGHT5);  
02321     pOpDesc->RemoveAlias();  
02322     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGERIGHT10);  
02323     pOpDesc->RemoveAlias();  
02324     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGERIGHTFIFTH);  
02325     pOpDesc->RemoveAlias();  
02326     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGERIGHTPIXEL1);  
02327     pOpDesc->RemoveAlias();  
02328     pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGERIGHTPIXEL10);  
02329     pOpDesc->RemoveAlias();  
02330 }
02331 
02332 /********************************************************************************************
02333 
02334 >   BOOL TranspTool::IsFillNudgeEnabled()
02335 
02336     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
02337     Created:    29/3/94
02338     Returns:    TRUE  - Fill nudging is disabled
02339                 FALSE - Fill nudging is enabled
02340     Purpose:    Checks for to see if the fill nudging is currently enabled or not.
02341     Errors:     -
02342                                                                  
02343 ********************************************************************************************/
02344 
02345 BOOL TranspTool::IsFillNudgeEnabled()
02346 {
02347     return NudgeFills;
02348 }
02349 
02350 /*****************************************************************************
02351 
02352 >   virtual BOOL TranspTool::GetStatusLineText(String_256* ptext, Spread* pSpread,
02353                                                  DocCoord DocPos, ClickModifiers ClickMods);
02354 
02355     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
02356     Created:    9/12/94
02357     Inputs:     pSpread   - pointer to spread under mouse (else NULL)
02358                 DocPos    - position of mouse in doc (in spread coords)
02359                 ClickMods - mouse click modifiers
02360     Outputs:    ptext - text for status line
02361     Returns:    TRUE if outputting valid text
02362     Purpose:    generate up-to-date text for the status line (called on idles)
02363 
02364 *****************************************************************************/
02365 
02366 BOOL TranspTool::GetStatusLineText(String_256* ptext, Spread* pSpread, 
02367                                      DocCoord DocPos, ClickModifiers ClickMods)
02368 {
02369     ERROR3IF(ptext==NULL,"TranspTool::GetStatusLineText() - ptext passed as null");
02370 
02371     if (ClickMods.Adjust)
02372         TempGeometryIndex = FGMENU_CIRCULARTRANSP;
02373     else
02374         TempGeometryIndex = -1;
02375 
02376     GetCursorAndStatus(DocPos, pSpread, NULL, ptext);
02377 
02378     return TRUE;
02379 }
02380 
02381 /********************************************************************************************
02382 
02383 >   void TranspTool::GetCursorAndStatus(DocCoord Pos, Spread* pSpread, 
02384                                           Cursor** pCursor, String_256* pStatus)
02385     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
02386     Created:    9/12/94
02387     Inputs:     Pos - The current position of the mouse.
02388     Purpose:    Get the correct cursor and status message for this mouse position.
02389 
02390 ********************************************************************************************/
02391 
02392 void TranspTool::GetCursorAndStatus(DocCoord Pos, Spread* pSpread, 
02393                                       Cursor** pCursor, String_256* pStatus)
02394 {
02395     // Setup defaults
02396     UINT32 Status;
02397     Cursor* pNewCursor = pTranspCursor;
02398 
02399     // Is the mouse over any of our fill control points ?
02400     if ( AttrFillGeometry::CheckForFillControlHit(Pos, &Status) )
02401     {
02402         // Status will have been updated
02403 
02404         // Change the cursor, to indicate the mouse is over a control point
02405         pNewCursor = pTranspPointCursor;
02406     }
02407     else
02408     {
02409         INT32 Index = pTranspInfoBarOp->CurrentGeometryIndex;
02410 
02411         if (TempGeometryIndex != -1)
02412             Index = TempGeometryIndex;
02413 
02414         // Check our menu status
02415         switch (Index)
02416         {      
02417             // If fill controls are selected then we indicate 
02418             // that a click will deselect them.
02419             // Otherwise we just show what kind of fill will
02420             // be created when the user drags.
02421 
02422             case (FGMENU_NOTRANSP):
02423                 if ( AttrFillGeometry::FillSelectionCount() > 0 )
02424                     Status = _R(IDS_TS_CREATELINEAR_S);     
02425                 else                                    
02426                     Status = _R(IDS_TS_CREATELINEAR);
02427                 break;
02428 
02429             case (FGMENU_FLATTRANSP):
02430                 if ( AttrFillGeometry::FillSelectionCount() > 0 )
02431                     Status = _R(IDS_TS_CREATELINEAR_S);     
02432                 else                                    
02433                     Status = _R(IDS_TS_CREATELINEAR);
02434                 break;
02435 
02436             case (FGMENU_LINEARTRANSP):
02437                 if ( AttrFillGeometry::FillSelectionCount() > 0 )
02438                     Status = _R(IDS_TS_CREATELINEAR_S);     
02439                 else                                    
02440                     Status = _R(IDS_TS_CREATELINEAR);
02441                 break;
02442 
02443             case (FGMENU_CIRCULARTRANSP):
02444                 if ( AttrFillGeometry::FillSelectionCount() > 0 )
02445                     Status = _R(IDS_TS_CREATECIRCLE_S);
02446                 else
02447                     Status = _R(IDS_TS_CREATECIRCLE);
02448                 break;
02449 
02450             case (FGMENU_RADIALTRANSP):
02451                 if ( AttrFillGeometry::FillSelectionCount() > 0 )
02452                     Status = _R(IDS_TS_CREATEELLIP_S);
02453                 else
02454                     Status = _R(IDS_TS_CREATEELLIP);
02455                 break;
02456 
02457             case (FGMENU_CONICALTRANSP):
02458                 if ( AttrFillGeometry::FillSelectionCount() > 0 )
02459                     Status = _R(IDS_TS_CREATECONICAL_S);
02460                 else
02461                     Status = _R(IDS_TS_CREATECONICAL);
02462                 break;
02463 
02464             case (FGMENU_SQUARETRANSP):
02465                 if ( AttrFillGeometry::FillSelectionCount() > 0 )
02466                     Status = _R(IDS_TS_CREATESQUARE_S);
02467                 else
02468                     Status = _R(IDS_TS_CREATESQUARE);
02469                 break;
02470 
02471             case (FGMENU_THREECOLTRANSP):
02472                 if ( AttrFillGeometry::FillSelectionCount() > 0 )
02473                     Status = _R(IDS_TS_CREATETHREECOL_S);
02474                 else
02475                     Status = _R(IDS_TS_CREATETHREECOL);
02476                 break;
02477 
02478             case (FGMENU_FOURCOLTRANSP):
02479                 if ( AttrFillGeometry::FillSelectionCount() > 0 )
02480                     Status = _R(IDS_TS_CREATEFOURCOL_S);
02481                 else
02482                     Status = _R(IDS_TS_CREATEFOURCOL);
02483                 break;
02484 
02485             case (FGMENU_BITMAPTRANSP):
02486                 if ( AttrFillGeometry::FillSelectionCount() > 0 )
02487                     Status = _R(IDS_TS_CREATEBITMAP_S);
02488                 else
02489                     Status = _R(IDS_TS_CREATEBITMAP);
02490                 break;
02491 
02492             case (FGMENU_FRACTALTRANSP):
02493                 if ( AttrFillGeometry::FillSelectionCount() > 0 )
02494                     Status = _R(IDS_TS_CREATEFRACTAL_S);
02495                 else
02496                     Status = _R(IDS_TS_CREATEFRACTAL);
02497                 break;
02498             
02499             case (FGMENU_NOISETRANSP):
02500                 if ( AttrFillGeometry::FillSelectionCount() > 0 )
02501                     Status = _R(IDS_TS_CREATENOISE_S);
02502                 else
02503                     Status = _R(IDS_TS_CREATENOISE);
02504                 break;
02505 
02506             default:
02507                 // Er .. Dunno what kind of fill this is ?
02508                 Status = _R(IDS_TS_CREATELINEAR);
02509                 break;
02510         }
02511     }
02512 
02513     if (pStatus != NULL)
02514     {
02515         pStatus->Load(Status);
02516         LastStatusID = Status;
02517     }
02518 
02519     if (pCursor != NULL)
02520         *pCursor = pNewCursor;
02521 }
02522 
02523 /********************************************************************************************
02524 
02525 >   static void TranspTool::DisplayStatusBarHelp(UINT32 StatusID)
02526 
02527     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
02528     Created:    9/8/94
02529     Inputs:     StatusID = ID of status help string
02530     Outputs:    -
02531     Returns:    -
02532     Purpose:    Displays the given status help string in the status bar
02533     SeeAlso:    -
02534 
02535 ********************************************************************************************/
02536 
02537 void TranspTool::DisplayStatusBarHelp(UINT32 StatusID)
02538 {
02539     String_256 StatusMsg("");
02540     StatusMsg.Load(StatusID);
02541     GetApplication()->UpdateStatusBarText(&StatusMsg);
02542     LastStatusID = StatusID;
02543 }
02544 
02545 
02546 
02549 
02550 //          Implementation of class GradInfoBarOp (graduated fill tool infobar)
02551 
02554 
02555 
02556 
02557 /********************************************************************************************
02558 
02559 >   struct FGMItem 
02560 
02561     Author:     Martin_Bell (Xara Group Ltd) <camelotdev@xara.com>
02562     Created:    23/06/97
02563     Purpose:    Associate the FillGeometry enum with the resource id of the text that gets
02564                 displayed on the menu.
02565     SeeAlso:    TGMItem, FillGeometry enum
02566 
02567 ********************************************************************************************/
02568 
02569 struct FGMItem
02570 {
02571     FillGeometry Geometry;
02572     unsigned StringID;
02573 };
02574 
02575 /********************************************************************************************
02576 
02577 >   const FGMItem FillGeometryMenu[] 
02578 
02579     Author:     Martin_Bell (Xara Group Ltd) <camelotdev@xara.com>
02580     Created:    23/06/97
02581     Purpose:    Array of 'FGMItem's that make up the geometry menu. We need to keep track of
02582                 this because list combo boxes can only return the position of the selected
02583                 item, not what it actually is. All this fuctionality should be in the gadgets
02584                 not here.
02585     SeeAlso:    FillGeometry enum, TransparencyGeometryMenu
02586 
02587 ********************************************************************************************/
02588 
02589 const FGMItem FillGeometryMenu[] =
02590 {
02591     { FGMENU_FLAT,      _R(IDS_FILLTOOL_FLATFILL) },
02592     { FGMENU_LINEAR,    _R(IDS_FILLTOOL_LINEAR) },
02593     { FGMENU_CIRCULAR,  _R(IDS_FILLTOOL_CIRCULAR) },
02594     { FGMENU_RADIAL,    _R(IDS_FILLTOOL_ELLIPTICAL) },
02595 #ifndef WEBSTER
02596     { FGMENU_CONICAL,   _R(IDS_FILLTOOL_CONICAL) },
02597     { FGMENU_SQUARE,    _R(IDS_FILLTOOL_SQUARE) },
02598     { FGMENU_THREECOL,  _R(IDS_FILLTOOL_THREECOL) },
02599     { FGMENU_FOURCOL,   _R(IDS_FILLTOOL_FOURCOL) },
02600 #endif //WEBSTER
02601     { FGMENU_BITMAP,    _R(IDS_FILLTOOL_BITMAP) },
02602     { FGMENU_FRACTAL,   _R(IDS_FILLTOOL_FRACTAL) },
02603 #ifndef WEBSTER
02604     { FGMENU_NOISE,     _R(IDS_FILLTOOL_NOISE) }
02605 #endif //WEBSTER
02606 };
02607 
02608 /********************************************************************************************
02609 
02610 >   const INT32 FillGeometryMenuCount 
02611 
02612     Author:     Martin_Bell (Xara Group Ltd) <camelotdev@xara.com>
02613     Created:    23/06/97
02614     Purpose:    Number of items on the FillGeometryMenu menu.
02615     SeeAlso:    FillGeometryMenu
02616 
02617 ********************************************************************************************/
02618 
02619 const INT32 FillGeometryMenuCount = sizeof(FillGeometryMenu) / sizeof(FillGeometryMenu[0]);
02620 
02621 /********************************************************************************************
02622 
02623 >   MsgResult GradInfoBarOp::Message(Msg* Message) 
02624 
02625     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
02626     Created:    3/8/94
02627     Inputs:     Message: The message to handle
02628     Outputs:    -
02629     Returns:    -
02630     Purpose:    Gradfill info bar dialog message handler
02631     Errors:     -
02632     SeeAlso:    -
02633 
02634 ********************************************************************************************/
02635 
02636 MsgResult GradInfoBarOp::Message(Msg* Message) 
02637 {
02638     if (!GradFillTool::IsCurrentTool() || !IsVisible())
02639     {
02640         return (InformationBarOp::Message(Message));
02641     }
02642 
02643     if (IS_OUR_DIALOG_MSG(Message))
02644     {
02645         DialogMsg* Msg = (DialogMsg*)Message;
02646 
02647         // Check if the message is a CANCEL
02648         if (Msg->DlgMsg == DIM_CANCEL)
02649         {
02650             Close(); // Close the dialog 
02651         }
02652         else if (Msg->DlgMsg == DIM_CREATE)
02653         {
02654             // Initialise the controls 
02655             InitControls();
02656         }
02657         else
02658         {
02659             if (Msg->GadgetID == _R(IDC_GEOMETRY))
02660             {
02661                 switch (Msg->DlgMsg)
02662                 {
02663                     case DIM_SELECTION_CHANGED :
02664                     {
02665                         ShowCommonType (FALSE);     // specifying false means that this
02666                                                     // gets (but does not show) CurrentGeometryIndex
02667                         
02668                         // Someone selected a new Fill Geometry
02669                         INT32 Index;
02670                         GetValueIndex(_R(IDC_GEOMETRY),&Index);
02671 
02672                         BOOL AllowFractal = FALSE;  // we need to still allow the user to
02673                                                     // select the same fractal fill
02674                                                     // again and again - since we apply a new
02675                                                     // seed on each occaison ....
02676 
02677                         if (Index == FGMENU_FRACTAL)
02678                         {
02679                             if (CurrentGeometryIndex == Index)
02680                             {
02681                                 AllowFractal = TRUE;
02682                             }
02683                         }
02684 
02685                         if (Index == FGMENU_NOISE)
02686                         {
02687                             if (CurrentGeometryIndex == Index)
02688                             {
02689                                 AllowFractal = TRUE;
02690                             }
02691                         }
02692                         
02693                         if ((CurrentGeometryIndex != Index) || (AllowFractal))
02694                         {
02695                             // Change the Fill Geometry Here
02696                             CurrentGeometryIndex = FillGeometryMenu[Index].Geometry;
02697 
02698                             // CGS - need to deselect all mult-stage fill blobs before
02699                             // chnaging the fill type - otherwise we get redraw problems ....
02700                             // Karim 30/11/2000 - rewritten to not use BevelTools,
02701                             // which is slower and carries memory-leak risks.
02702                             Range* pSelRange = GetApplication()->FindSelection();
02703                             if (pSelRange != NULL)
02704                             {
02705                                 for ( Node* pSelNode =  pSelRange->FindFirst();
02706                                             pSelNode != NULL;
02707                                             pSelNode =  pSelRange->FindNext(pSelNode) )
02708                                 {
02709                                     if (pSelNode->IsAnAttribute() &&
02710                                         pSelNode->IS_KIND_OF(AttrFillGeometry))
02711                                     {
02712                                         FillRamp* pRamp = ((AttrFillGeometry*)pSelNode)->GetFillRamp();
02713                                         if (pRamp != NULL)
02714                                             pRamp->DeselectAll();
02715                                     }
02716                                 }
02717                             }
02718                             
02719                             ChangeFillType();
02720                             EnableControls();
02721                         }
02722                     }
02723                     break;
02724 
02725                     default:
02726                         break;
02727                 }
02728             }
02729 
02730             else if (Msg->GadgetID == _R(IDC_MAPPING))
02731             {
02732                 switch (Msg->DlgMsg)
02733                 {
02734                     case DIM_SELECTION_CHANGED:
02735                     {
02736                         ShowCommonMapping (FALSE);      // specifying false means that this
02737                                                         // gets (but does not show) CurrentMappingIndex
02738                         
02739                         // Someone selected a new Fill Mapping
02740                         INT32 Index;  
02741                         GetValueIndex(_R(IDC_MAPPING),&Index);
02742 
02743                         if (CurrentMappingIndex != Index)
02744                         {
02745                             // Change the Fill Mapping Here
02746                             CurrentMappingIndex = Index;
02747                             ChangeFillMapping();
02748                         }
02749                     }
02750                     break;
02751 
02752                     default:
02753                         break;
02754                 }
02755             }
02756 
02757             else if (Msg->GadgetID == _R(IDC_EFFECT))
02758             {
02759                 switch (Msg->DlgMsg)
02760                 {
02761                     case DIM_SELECTION_CHANGED:
02762                     {
02763                         ShowCommonEffect (FALSE);   // specifying false means that this
02764                                                     // gets (but does not show) CurrentEffectIndex
02765                         
02766                         // Someone selected a new Fill Effect
02767                         INT32 Index;  
02768                         GetValueIndex(_R(IDC_EFFECT),&Index);
02769 
02770                         if (CurrentEffectIndex != Index)
02771                         {
02772                             // Change the Fill Effect Here
02773                             CurrentEffectIndex = Index;
02774                             ChangeFillEffect();
02775                         }
02776                     }
02777                     break;
02778 
02779                     default:
02780                         break;
02781                 }
02782             }
02783 
02784             else if (Msg->GadgetID == _R(IDC_BITMAPEFFECT))
02785             {
02786                 switch (Msg->DlgMsg)
02787                 {
02788                     case DIM_SELECTION_CHANGED:
02789                     {
02790                         // Someone selected a new bitmap Fill Effect
02791                         INT32 iIndex = m_oBitmapDropDown.GetSelected();
02792                         // GetValueIndex (_R(IDC_BITMAPEFFECT), &Index);
02793 
02794 
02795                         //if (CurrentEffectIndex != Index)
02796                         //{
02797                             // Change the bitmap Fill Effect Here
02798                             // (we use CurrentEffectIndex because of the days when
02799                             // _R(IDC_EFFECT) handled this as well; thus we avoid having
02800                             // to change all of the code that relates to this
02801                             CurrentEffectIndex = iIndex;
02802                             ChangeBitmapName ();
02803                         //}
02804                     }
02805                     break;
02806 
02807                     default:
02808                         break;
02809                 }
02810             }
02811 
02812             else if (Msg->GadgetID == _R(IDC_BIASGAIN))
02813             {
02814                 switch (Msg->DlgMsg)
02815                 {
02816                     case DIM_LFT_BN_CLICKED:
02817                         HandleProfileButtonClick (m_BiasGainGadget, _R(IDC_BIASGAIN));
02818                         break;
02819 
02820                     default:
02821                         ProfileSelectionChange( Msg, Msg->GadgetID );
02822                         break;
02823                 }
02824             }
02825 
02826             else if (Msg->GadgetID == _R(IDC_SELPOINT))
02827             {
02828                 switch (Msg->DlgMsg)
02829                 {
02830                     case DIM_SELECTION_CHANGED:
02831                     {
02832                         if (AttrFillGeometry::SelectionCount == 0)
02833                         {
02834                             if (Mode == BITMAPFILL || 
02835                                 Mode == FRACTALFILL || 
02836                                 Mode == NOISEFILL ) 
02837                             {
02838                                 ChangeDPI();
02839                             }
02840                         }
02841                     }
02842                     break;
02843                     default:
02844                         break;
02845                 }
02846             }
02847 
02848             else if (Msg->GadgetID == _R(IDC_SELCOLOUR))
02849             {
02850                 switch (Msg->DlgMsg)
02851                 {
02852                     case DIM_SELECTION_CHANGED:
02853                     {
02854                         if (AttrFillGeometry::SelectionCount == 0)
02855                         {
02856                             if (Mode == FRACTALFILL)
02857                                 ChangeFractalGrain();
02858                             if (Mode == NOISEFILL)
02859                                 ChangeNoiseScale();
02860                         }
02861                     }
02862                     break;
02863 
02864                     default:
02865                         break;
02866                 }
02867             }
02868         }
02869     }
02870 
02871     if (MESSAGE_IS_A(Message, SelChangingMsg) ||
02872         MESSAGE_IS_A(Message, CurrentAttrChangedMsg))
02873     {
02874         // The selection has changed in some way
02875         // Re-Count the number of selected fill control points
02876         AttrFillGeometry::SetSelectionCount(AttrFillGeometry::CountSelectionControlPoints());
02877 
02878         if (AttrFillGeometry::SelectionCount > 0)
02879         {
02880             GradFillTool::EnableFillNudge();
02881         }
02882         else
02883         {
02884             GradFillTool::DisableFillNudge();
02885         }
02886 
02887         HandleProfileSelChangingMsg (m_BiasGainGadget, _R(IDC_BIASGAIN));
02888 
02889         ShowInfo();
02890 /*
02891         SelChangingMsg* Msg = (SelChangingMsg*)Message;
02892         switch (Msg->State)
02893         {
02894             case SelChangingMsg::COLOURATTCHANGED:
02895                 // The colour of an attribute has changed
02896                 TRACEUSER( "Will", _T("ColourAttChanged\n"));
02897                 InitControls();
02898                 break;
02899 
02900             case SelChangingMsg::NONCOLOURATTCHANGED:
02901                 // The selection state or control points of an attribute have changed
02902                 TRACEUSER( "Will", _T("NonColourAttChanged\n"));
02903                 InitControls();
02904                 break;
02905         }
02906 */
02907     }
02908 
02909     // do we have a selection change message? 
02910     if (MESSAGE_IS_A(Message, SelChangingMsg))
02911     {
02912         //ShowInfo();       // done in above call anyway - so not needed here ....
02913         HandleProfileSelChangingMsg (m_BiasGainGadget, _R(IDC_BIASGAIN));
02914         ShowInfo();
02915     }
02916 
02917     if (MESSAGE_IS_A(Message, BitmapListChangedMsg) &&
02918         Document::GetSelected() != NULL)
02919     {   
02920         InitBitmapName();
02921         ShowInfo();
02922     }
02923     
02924     // Pass the message on
02925     return (InformationBarOp::Message(Message));
02926 }    
02927 
02928 
02929 
02930 /********************************************************************************************
02931 
02932 >   void GradInfoBarOp::ChangeProfile(CProfileBiasGain* Profile, CGadgetID GadgetID)
02933 
02934     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
02935     Created:    7/2/2000
02936     Purpose:    See InformationBarOp::ChangeProfile () for an explanation of this function.
02937     See Also:   InformationBarOp::ChangeProfile ()
02938 
02939 *********************************************************************************************/
02940 
02941 void GradInfoBarOp::ChangeProfile(CProfileBiasGain* Profile, CGadgetID GadgetID)
02942 {
02943     OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_FILLPROFILE);
02944     if (pOpDesc != NULL)
02945     {           
02946         BOOL FireOp = TRUE;
02947 
02948         // we only want to generate one bit of undo information - so decided whether
02949         // we have to fire the above op, or whether we just 'pump' the values into
02950         // our nodes (thereby nolonger generating infinite undo information) ....
02951 
02952         Operation* pLastOp = NULL;
02953 
02954         if (Profile->GetGeneratesInfiniteUndo ())   // only do if they didn't select a preset profile
02955         {
02956             pLastOp = Document::GetSelected()->GetOpHistory().FindLastOp();
02957         }
02958 
02959         if (pLastOp)
02960         {
02961             if (pLastOp->GetRuntimeClass() == CC_RUNTIME_CLASS(OpChangeFillProfile))
02962             {
02963                 FireOp = FALSE;
02964             }
02965         }
02966 
02967         if (FireOp == TRUE)
02968         {
02969             FillProfileOpParam Param;
02970             Param.Profile = *Profile;
02971         
02972             pOpDesc->Invoke(&Param);
02973         }
02974         else
02975         {
02976             // we don't need/want any undo information - so just change the value ....
02977             
02978             //OpChangeFillProfile Op;
02979             ChangeFillProfileAction Action;
02980             Action.ChangeFillProfileWithNoUndo (/*&Op,*/ *Profile);
02981         }
02982     }
02983 }
02984 
02985 
02986 
02987 /********************************************************************************************
02988 
02989 >   virtual CProfileBiasGain* GetProfileFromSelection(CGadgetID GadgetID, INT32* Index, BOOL* bAllSameType)
02990 
02991     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
02992     Created:    7/2/2000
02993     Inputs:     The GadgetID of the CBiasGainGadget that we are dealing with.
02994     Outputs:    bMany - returned as TRUE if we have MANY profiles selected.
02995                 bAllSameType - returned as TRUE if objects within selection are all of the
02996                 same type.
02997     returns     Ptr to common CProfileBiasGain, or NULL if there is NOT one.
02998     Purpose:    See InformationBarOp::GetProfileFromSelection () for a description of this
02999                 function.
03000 
03001 *********************************************************************************************/
03002 
03003 CProfileBiasGain* GradInfoBarOp::GetProfileFromSelection(CGadgetID GadgetID, BOOL* bMany, BOOL* bAllSameType)
03004 {
03005     BOOL ok = (GadgetID == _R(IDC_BIASGAIN));
03006 
03007     ERROR2IF(ok==FALSE, FALSE, "Invalid gadgetID passed");
03008     
03009     UINT32 TotalNumberSelected = (GetApplication()->FindSelection()->Count ());
03010     
03011     // get the list of all the shadows
03012     List ShadowList;
03013 //  FillTools::BuildListOfSelectedNodes(&ShadowList, CC_RUNTIME_CLASS(AttrFillGeometry));
03014     FillTools::GetSelectedAttrList(&ShadowList, CC_RUNTIME_CLASS(AttrFillGeometry), TRUE, FALSE);
03015 
03016     AttrFillGeometry* pFirstNodeShadow = NULL;
03017     FillGeometryAttribute* pFirstFillGeoAttr = NULL;
03018 
03019     //CProfileBiasGain Profile;
03020     CProfileBiasGain* pFirstProfile = NULL;
03021 
03022     /*if (TotalNumberSelected != (UINT32) ShadowList.GetCount ())
03023     {
03024         // totals differ - so the user MUST have selected someother type of node as well
03025         *bAllSameType = FALSE;
03026         ShadowList.DeleteAll();
03027         return (NULL);
03028     }*/
03029 
03030     NodeListItem * pItem = (NodeListItem *)ShadowList.GetHead();
03031 
03032     while (pItem)
03033     {
03034         if (pFirstNodeShadow == NULL)
03035         {
03036             pFirstNodeShadow = (AttrFillGeometry*) pItem->pNode;
03037             pFirstFillGeoAttr = (FillGeometryAttribute*) pFirstNodeShadow->GetAttributeValue ();
03038 
03039             pFirstProfile = pFirstFillGeoAttr->GetProfilePtr ();
03040 
03041             if (pFirstNodeShadow->GetFillRamp () != NULL)
03042             {
03043                 *bAllSameType = FALSE;
03044             }
03045         }
03046         else
03047         {       
03048             if (((AttrFillGeometry*)pItem->pNode)->GetFillRamp () != NULL)
03049             {
03050                 *bAllSameType = FALSE;
03051             }
03052 
03053             CProfileBiasGain* pOtherProfile = NULL;
03054 
03055             pOtherProfile = ((FillGeometryAttribute*) ((AttrFillGeometry*)pItem->pNode)->GetAttributeValue ())->GetProfilePtr ();
03056 
03057             if (pOtherProfile)
03058             {
03059                 if (*pFirstProfile == *pOtherProfile)
03060                 {
03061                     // all ok
03062                 }
03063                 else
03064                 {
03065                     *bMany = TRUE;
03066                 }
03067             }
03068         }
03069 
03070         pItem = (NodeListItem *)ShadowList.GetNext(pItem);
03071     }
03072 
03073     if (TotalNumberSelected != (UINT32) ShadowList.GetCount ())
03074     {
03075         // totals differ - so the user MUST have selected someother type of node as well
03076         
03077         if ((pFirstProfile) && (*bMany == FALSE))
03078         {
03079             // scan each node in the list, and see if they have the attribute applied ....
03080 
03081             SelRange* range = GetApplication()->FindSelection();
03082 
03083             NodeRenderableInk* pNode = (NodeRenderableInk*) range->FindFirst ();
03084             NodeAttribute* pAttr;
03085 
03086             while (pNode)
03087             {
03088                 if (pNode->FindAppliedAttribute (CC_RUNTIME_CLASS (AttrFillGeometry), &pAttr))
03089                 {
03090                     pNode = (NodeRenderableInk*) (range->FindNext (pNode));
03091                 }
03092                 else
03093                 {
03094                     // the node ain't got one
03095 
03096                     *bAllSameType = FALSE;
03097                     ShadowList.DeleteAll();
03098                     return (NULL);
03099                 }
03100             }
03101         }
03102         else
03103         {   
03104             *bAllSameType = FALSE;
03105             ShadowList.DeleteAll();
03106             return (NULL);
03107         }
03108     }
03109     if (m_BiasGainGadget.GetUseFillProfile () == FALSE)     // biasgain dialog is configured
03110     {                                                       // as an 'object' spacing
03111         ShadowList.DeleteAll();
03112         if (*bMany == TRUE)
03113         {
03114             return (NULL);
03115         }
03116         else
03117         {
03118             return (pFirstProfile);
03119         }
03120     }
03121     else        // biasgain dialog is configured as an interpolation (between two colours)
03122     {
03123         // so we had best attempt to get them ....
03124         if (*bMany == TRUE)             // don't matter in this case anyway
03125         {
03126             ShadowList.DeleteAll();
03127             return (NULL);
03128         }
03129         else
03130         {
03131             // BUT it does here ....
03132             // NOTE:  we can only be 'context' sensitive for a single fill within the
03133             // selection - so lets just choose the first one that we came accross ....
03134 
03135             if (pFirstNodeShadow)
03136             {   
03137                 m_BiasGainGadget.SetStartColour (pFirstNodeShadow->GetStartColour ());
03138                 m_BiasGainGadget.SetEndColour (pFirstNodeShadow->GetEndColour ());
03139 
03140                 // we also need to find ourselves an effect type (i.e.  fade, rainbow or alt rainbow)
03141 
03142                 String_64 Str;
03143 
03144                 CommonAttrEffect = SelRange::ATTR_NONE;
03145                 Str.Load(_R(IDS_FILLTOOL_NONE));
03146 
03147                 if (Selection != NULL)
03148                 {
03149                     // Try and find a common Attribute within the selection.
03150                     // All objects in the selection must have an Identical fill for this
03151                     // to find anything.
03152                     CommonAttrEffect = Selection->FindCommonAttribute(CC_RUNTIME_CLASS(AttrFillEffect), 
03153                                                                 (NodeAttribute**)&CommonEffect);
03154                     CCRuntimeClass* EffectType;
03155 
03156                     // Try and find a common Attribute Type within the selection.
03157                     // The fills need not be identical. Just of the same type.
03158                     SelRange::CommonAttribResult CommonType = 
03159                             Selection->FindCommonAttributeType(CC_RUNTIME_CLASS(AttrFillEffect), 
03160                                                                 &EffectType);
03161 
03162                     if (CommonAttrEffect == SelRange::ATTR_NONE &&
03163                         CommonEffect != NULL)
03164                     {
03165                         CommonAttrEffect = SelRange::ATTR_COMMON;
03166                     }
03167 
03168                     if (CommonType == SelRange::ATTR_NONE &&
03169                         EffectType != NULL)
03170                     {
03171                         CommonType = SelRange::ATTR_COMMON;
03172                     }
03173 
03174                     FillEffectAttribute* TheEffect = NULL;
03175     
03176                     // Make the menu show any Common Fill Type
03177                     // or failing that, 'None' or 'Many'.
03178                     if (CommonType == SelRange::ATTR_COMMON)
03179                     {   
03180                         if (EffectType == CC_RUNTIME_CLASS(AttrFillEffectFade))
03181                         {
03182                             TheEffect = new FillEffectFadeAttribute ();
03183                         }
03184                         else if (EffectType == CC_RUNTIME_CLASS(AttrFillEffectRainbow))
03185                         {
03186                             TheEffect = new FillEffectRainbowAttribute ();
03187                         }
03188                         else if (EffectType == CC_RUNTIME_CLASS(AttrFillEffectAltRainbow))
03189                         {
03190                             TheEffect = new FillEffectAltRainbowAttribute ();
03191                         }
03192                     }
03193 
03194                     if (CommonEffect != NULL)
03195                         m_BiasGainGadget.SetFillEffect (TheEffect);
03196 
03197             //      delete (TheEffect);
03198                 }
03199                 // else we can't alter the fill effect
03200 
03201                 ShadowList.DeleteAll();
03202             }
03203             
03204             return (pFirstProfile);
03205         }
03206     }
03207 }
03208 
03209 
03210 
03211 /********************************************************************************************
03212 
03213 >   void GradInfoBarOp::InitControls()
03214 
03215     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
03216     Created:    3/8/94
03217     Purpose:    Inits all the controls in the info bar.
03218                 Called immediately after the bar is created when the gradfill tool
03219                 becomes the current tool.
03220     SeeAlso:    -
03221 
03222 ********************************************************************************************/
03223 
03224 void GradInfoBarOp::InitControls()
03225 {
03226     // Don't do anything if the Info bar isn't displayed
03227     if (!GradFillTool::IsCurrentTool() || !IsVisible()) return;
03228 
03229     DeleteAllValues(_R(IDC_GEOMETRY));
03230     DeleteAllValues(_R(IDC_EFFECT));
03231 //  DeleteAllValues(_R(IDC_BITMAPEFFECT));
03232     DeleteAllValues(_R(IDC_MAPPING));
03233 
03234     m_oBitmapDropDown.Init(WindowID, _R(IDC_BITMAPEFFECT));
03235     m_oBitmapDropDown.SetColumns(3);
03236     m_oBitmapDropDown.SetItemSize(wxSize(50, 50));
03237 
03238     String_64 Str;
03239 
03240     // Setup the Menu Item text entries
03241     for ( INT32 i=0; i<FillGeometryMenuCount; i++ )
03242     {
03243         Str.Load( FillGeometryMenu[i].StringID );
03244         SetStringGadgetValue( _R(IDC_GEOMETRY), Str, TRUE, FillGeometryMenu[i].Geometry );
03245     }
03246 
03247     // Ensure the drop-downs are the correct length
03248     SetComboListLength(_R(IDC_GEOMETRY));
03249 
03250     SetGadgetWritable(_R(IDC_GEOMETRY), FALSE);
03251     SetGadgetWritable(_R(IDC_MAPPING), FALSE);
03252     SetGadgetWritable(_R(IDC_EFFECT), FALSE);
03253     SetGadgetWritable(_R(IDC_SELPOINT), FALSE);
03254     SetGadgetWritable(_R(IDC_SELCOLOUR), FALSE);
03255 
03256     SetGadgetHelp(_R(IDC_GEOMETRY),     _R(IDBBL_FILLTOOL_FILLTYPE),        _R(IDS_FILLTOOL_FILLTYPE));
03257     SetGadgetHelp(_R(IDC_EFFECT),       _R(IDBBL_FILLTOOL_FILLEFFECT),      _R(IDS_FILLTOOL_FILLEFFECT));
03258     SetGadgetHelp(_R(IDC_BITMAPEFFECT), _R(IDBBL_FILLTOOL_BITMAPNAME),      _R(IDS_FILLTOOL_BITMAPNAME));
03259     SetGadgetHelp(_R(IDC_MAPPING),      _R(IDBBL_FILLTOOL_FILLTILING),      _R(IDS_FILLTOOL_FILLTILING));
03260     SetGadgetHelp(_R(IDC_SELPOINT),     _R(IDBBL_FILLTOOL_FILLHANDLE),      _R(IDS_FILLTOOL_FILLHANDLE));
03261 
03262     // Default to the first items in each list
03263     SelGeometryIndex = 0;
03264     SelMappingIndex = 0;
03265     SelEffectIndex = 0;
03266     SelPointIndex = 0;
03267 
03268     CommonGeometry = NULL;
03269     CommonMapping = NULL;
03270     CommonEffect = NULL;
03271 
03272     MappingDisabled = FALSE;
03273     EffectDisabled = FALSE;
03274     AllowForceToSimpleMapping = TRUE;
03275 
03276     Mode = NOFILL;
03277 
03278     m_BiasGainGadget.Init(this, _R(IDC_BIASGAIN), _R(IDBBL_BIASGAIN),  _R(IDS_BIASGAINDLG));
03279     m_BiasGainGadget.ToggleFillProfile ();
03280 
03281     ShowInfo();
03282 }           
03283 
03284 /********************************************************************************************
03285 
03286 >   void GradInfoBarOp::ShowInfo()
03287 
03288     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
03289     Created:    8/5/95
03290     Purpose:    Shows Info on the current selection.
03291     SeeAlso:    -
03292 
03293 ********************************************************************************************/
03294 
03295 void GradInfoBarOp::ShowInfo()
03296 {
03297     // Don't do anything if the Info bar isn't displayed
03298     if (!GradFillTool::IsCurrentTool() || !IsVisible()) return;
03299 
03300     // Now have a look at the selected objects
03301     Selection = GetApplication()->FindSelection();
03302 
03303     OldMode = Mode;
03304 
03305     ShowCommonType();
03306 
03307     // Now show different info depending on the type ...
03308     // (Well we will do eventually)
03309 
03310     switch (Mode)
03311     {
03312         case FLATFILL:
03313             ShowFlatInfo();
03314             break;
03315 
03316         case GRADFILL:
03317         case GRADREPEATFILL:
03318             ShowGraduatedInfo();
03319             break;
03320 
03321         case BITMAPFILL:
03322             ShowBitmapInfo();
03323             break;
03324 
03325         case FRACTALFILL:
03326             ShowFractalInfo();
03327             break;
03328 
03329         case NOISEFILL:
03330             ShowNoiseInfo();
03331             break;
03332 
03333         default:
03334             ShowGraduatedInfo();
03335             break;
03336     }
03337 
03338     EnableControls();
03339 }
03340 
03341 /********************************************************************************************
03342 
03343 >   void GradInfoBarOp::InitEffect()
03344 
03345     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
03346     Created:    8/5/95
03347     Purpose:    Initialise the Effect Control.
03348     SeeAlso:    -
03349 
03350 ********************************************************************************************/
03351 
03352 void GradInfoBarOp::InitEffect()
03353 {
03354     DeleteAllValues(_R(IDC_EFFECT));
03355     EnableGadget(_R(IDC_EFFECT), TRUE);
03356     EffectDisabled = FALSE;
03357 
03358     String_64 Str;
03359 
03360     Str.Load(_R(IDS_FILLTOOL_FADE));
03361     SetStringGadgetValue(_R(IDC_EFFECT),Str,FALSE, FEMENU_FADE);
03362     Str.Load(_R(IDS_FILLTOOL_RAINBOW));
03363     SetStringGadgetValue(_R(IDC_EFFECT),Str,FALSE, FEMENU_RAINBOW);
03364     Str.Load(_R(IDS_FILLTOOL_ALTRAINBOW));
03365     SetStringGadgetValue(_R(IDC_EFFECT),Str,TRUE, FEMENU_ALTRAINBOW);
03366 
03367     SetComboListLength(_R(IDC_EFFECT));
03368 }
03369 
03370 /********************************************************************************************
03371 
03372 >   void GradInfoBarOp::InitMapping()
03373 
03374     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
03375     Created:    8/5/95
03376     Purpose:    Initialise the Mapping Control.
03377     SeeAlso:    -
03378 
03379 ********************************************************************************************/
03380 
03381 void GradInfoBarOp::InitMapping()
03382 {
03383     DeleteAllValues(_R(IDC_MAPPING));
03384     EnableGadget(_R(IDC_MAPPING), TRUE);
03385     MappingDisabled = FALSE;
03386 
03387     String_64 Str;
03388 
03389     Str.Load(_R(IDS_FILLTOOL_MAPSIMPLE));
03390     SetStringGadgetValue(_R(IDC_MAPPING),Str,FALSE, FMMENU_SIMPLE);
03391     Str.Load(_R(IDS_FILLTOOL_MAPREPEAT));
03392     SetStringGadgetValue(_R(IDC_MAPPING),Str,TRUE, FMMENU_REPEATING);
03393 
03394 //  SetSelectedValueIndex(_R(IDC_MAPPING), 0);
03395     SetComboListLength(_R(IDC_MAPPING));
03396 }
03397 
03398 /********************************************************************************************
03399 
03400 >   void GradInfoBarOp::InitBitmapName()
03401 
03402     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
03403     Created:    8/5/95
03404     Purpose:    Initialise the Bitmap Name Control.
03405     SeeAlso:    -
03406 
03407 ********************************************************************************************/
03408 
03409 void GradInfoBarOp::InitBitmapName()
03410 {
03411 //  DeleteAllValues(_R(IDC_BITMAPEFFECT));
03412     m_oBitmapDropDown.Clear();
03413     EnableGadget (_R(IDC_BITMAPEFFECT), TRUE);
03414     
03415     EffectDisabled = FALSE;
03416 
03417     Document* pDoc = Document::GetSelected();
03418 
03419     // Get the bitmap list
03420     BitmapList* Bitmaps = NULL;
03421     if (pDoc) Bitmaps = pDoc->GetBitmapList();
03422 
03423     if (Bitmaps == NULL)
03424         return;
03425 
03426     String_256 Str;
03427 
03428     if (Bitmaps->GetCount() > 0)
03429     {
03430         INT32 Index = 0;
03431 
03432         ListItem* pBmp = Bitmaps->GetHead();
03433 
03434 
03435         while (pBmp != NULL)
03436         {
03437             if (!((KernelBitmap*)pBmp)->HasBeenDeleted())   // Ignore deleted bitmaps
03438             {
03439                 Str = ((KernelBitmap*)pBmp)->ActualBitmap->GetName();
03440 
03441                 KernelBitmap* bitmap = ((KernelBitmap*)pBmp);
03442                 m_oBitmapDropDown.AddItem(bitmap, FALSE, Str);
03443                 
03444                 Index++;
03445             }
03446 
03447             pBmp = Bitmaps->GetNext(pBmp);
03448         }
03449 
03450     }
03451 }
03452 
03453 
03454 /********************************************************************************************
03455 
03456 >   void GradInfoBarOp::InitTesselate()
03457 
03458     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
03459     Created:    8/5/95
03460     Purpose:    Initialise the Tesselation Control.
03461     SeeAlso:    -
03462 
03463 ********************************************************************************************/
03464 
03465 void GradInfoBarOp::InitTesselate()
03466 {
03467     DeleteAllValues(_R(IDC_MAPPING));
03468     EnableGadget(_R(IDC_MAPPING), TRUE);
03469     MappingDisabled = FALSE;
03470 
03471     String_64 Str;
03472 
03473     Str.Load(_R(IDS_FILLTOOL_TESS_SIMPLE));
03474     SetStringGadgetValue(_R(IDC_MAPPING),Str,FALSE, FTMENU_SIMPLE);
03475     Str.Load(_R(IDS_FILLTOOL_TESS_REPEAT));
03476     SetStringGadgetValue(_R(IDC_MAPPING),Str,FALSE, FTMENU_REPEAT);
03477     Str.Load(_R(IDS_FILLTOOL_TESS_REPEATINV));
03478     SetStringGadgetValue(_R(IDC_MAPPING),Str,TRUE, FTMENU_REPEATINV);
03479 
03480     SetComboListLength(_R(IDC_MAPPING));
03481 }
03482 
03483 /********************************************************************************************
03484 
03485 >   BOOL GradInfoBarOp::SetGadgetString(CGadgetID Gadget, StringBase* StrValue)
03486 
03487     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
03488     Created:    8/5/95
03489     Purpose:    Set the string displayed by a Gadget.
03490                 This version only updates the gadget if it has changed.
03491     SeeAlso:    -
03492 
03493 ********************************************************************************************/
03494 
03495 BOOL GradInfoBarOp::SetGadgetString(CGadgetID Gadget, StringBase* StrValue)
03496 {
03497     if (Gadget == _R(IDC_EFFECT) && EffectDisabled)
03498         return TRUE;
03499 
03500     if (Gadget == _R(IDC_MAPPING) && MappingDisabled)
03501         return TRUE;
03502 
03503     if (GetStringGadgetValue(Gadget, NULL, -1) != *StrValue)
03504     {
03505         return SetStringGadgetValue(Gadget, *StrValue, FALSE, -1);
03506     }
03507 
03508     return TRUE;
03509 }
03510 
03511 /********************************************************************************************
03512 
03513 >   void GradInfoBarOp::ShowFlatInfo()
03514 
03515     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
03516     Created:    20/10/94
03517     Purpose:    Show info on a flat fill.
03518 
03519 ********************************************************************************************/
03520 
03521 void GradInfoBarOp::ShowFlatInfo()
03522 {
03523     if (OldMode != FLATFILL)
03524     {   
03525         InitMapping();
03526         InitEffect();
03527 
03528         SetGadgetHelp(_R(IDC_EFFECT),       _R(IDBBL_FILLTOOL_FILLEFFECT),      _R(IDS_FILLTOOL_FILLEFFECT));
03529         SetGadgetHelp(_R(IDC_MAPPING),      _R(IDBBL_FILLTOOL_FILLTILING),      _R(IDS_FILLTOOL_FILLTILING));
03530         SetGadgetHelp(_R(IDC_SELPOINT),     _R(IDBBL_FILLTOOL_FILLHANDLE),      _R(IDS_FILLTOOL_FILLHANDLE));
03531         //SetGadgetHelp(_R(IDC_SELCOLOUR),  _R(IDBBL_FILLTOOL_FILLCOLOUR),      _R(IDS_FILLTOOL_FILLCOLOUR));
03532     }
03533 
03534     ShowCommonEffect();
03535     ShowCommonMapping();
03536     ShowControlPointInfo();
03537 }
03538 
03539 /********************************************************************************************
03540 
03541 >   void GradInfoBarOp::ShowGraduatedInfo()
03542 
03543     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
03544     Created:    20/10/94
03545     Purpose:    Show info on a graduated fill.
03546 
03547 ********************************************************************************************/
03548 
03549 void GradInfoBarOp::ShowGraduatedInfo()
03550 {
03551     if (OldMode != GRADFILL && OldMode != GRADREPEATFILL)
03552     {   
03553         InitMapping();
03554         InitEffect();
03555 
03556         SetGadgetHelp(_R(IDC_EFFECT),       _R(IDBBL_FILLTOOL_FILLEFFECT),      _R(IDS_FILLTOOL_FILLEFFECT));
03557         SetGadgetHelp(_R(IDC_MAPPING),      _R(IDBBL_FILLTOOL_FILLTILING),      _R(IDS_FILLTOOL_FILLTILING));
03558         SetGadgetHelp(_R(IDC_SELPOINT),     _R(IDBBL_FILLTOOL_FILLHANDLE),      _R(IDS_FILLTOOL_FILLHANDLE));
03559         //SetGadgetHelp(_R(IDC_SELCOLOUR),  _R(IDBBL_FILLTOOL_FILLCOLOUR),      _R(IDS_FILLTOOL_FILLCOLOUR));
03560     }
03561 
03562     ShowCommonEffect();
03563     ShowCommonMapping();
03564     ShowControlPointInfo();
03565 }
03566 
03567 /********************************************************************************************
03568 
03569 >   void GradInfoBarOp::ShowBitmapInfo()
03570 
03571     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
03572     Created:    20/10/94
03573     Purpose:    Show info on a bitmap fill.
03574 
03575 ********************************************************************************************/
03576 
03577 void GradInfoBarOp::ShowBitmapInfo()
03578 {
03579     if (OldMode != BITMAPFILL)
03580     {
03581         InitTesselate ();
03582         InitEffect ();              // we need to do this because of the possibility of contoned bitmaps ....
03583         InitBitmapName ();
03584 
03585         SetGadgetHelp(_R(IDC_BITMAPEFFECT), _R(IDBBL_FILLTOOL_BITMAPNAME),      _R(IDS_FILLTOOL_BITMAPNAME));
03586         SetGadgetHelp(_R(IDC_MAPPING),      _R(IDBBL_FILLTOOL_FILLTILING),      _R(IDS_FILLTOOL_FILLTILING));
03587         //SetGadgetHelp(_R(IDC_SELCOLOUR),  _R(IDBBL_FILLTOOL_FILLCOLOUR),      _R(IDS_FILLTOOL_FILLCOLOUR));
03588     }
03589 
03590     if (AttrFillGeometry::SelectionCount == 0)
03591     {
03592         SetGadgetHelp(_R(IDC_SELPOINT),  _R(IDBBL_FILLTOOL_BITMAPRES),  _R(IDS_FILLTOOL_BITMAPRES));
03593         SetGadgetWritable(_R(IDC_SELPOINT), TRUE);
03594     }
03595     else
03596     {
03597         SetGadgetHelp(_R(IDC_SELPOINT),  _R(IDBBL_FILLTOOL_FILLHANDLE), _R(IDS_FILLTOOL_FILLHANDLE));
03598         SetGadgetWritable(_R(IDC_SELPOINT), FALSE);
03599     }
03600 
03601     ShowCommonTesselate();
03602     ShowCommonEffect ();
03603     ShowCommonBitmapName();
03604     ShowControlPointInfo();
03605 
03606     if (AttrFillGeometry::SelectionCount == 0)
03607         ShowCommonBitmapDpi();
03608 }
03609 
03610 
03611 
03612 /********************************************************************************************
03613 
03614 >   void GradInfoBarOp::ShowFractalInfo()
03615 
03616     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
03617     Created:    20/10/94
03618     Purpose:    Show info on a fractal fill.
03619 
03620 ********************************************************************************************/
03621 
03622 void GradInfoBarOp::ShowFractalInfo()
03623 {
03624     if (OldMode != FRACTALFILL)
03625     {   
03626 //      InitTransType ();
03627         InitTesselate();
03628         InitEffect();
03629 
03630         SetGadgetHelp(_R(IDC_EFFECT),    _R(IDBBL_FILLTOOL_FILLEFFECT), _R(IDS_FILLTOOL_FILLEFFECT));
03631         SetGadgetHelp(_R(IDC_MAPPING),   _R(IDBBL_FILLTOOL_FILLTILING), _R(IDS_FILLTOOL_FILLTILING));
03632     }
03633 
03634     if (AttrFillGeometry::SelectionCount == 0)
03635     {
03636         SetGadgetHelp(_R(IDC_SELPOINT),  _R(IDBBL_FILLTOOL_FRACTALRES),  _R(IDS_FILLTOOL_FRACTALRES));
03637         SetGadgetHelp(_R(IDC_SELCOLOUR), _R(IDBBL_FILLTOOL_GRAININESS), _R(IDS_FILLTOOL_GRAININESS));
03638         SetGadgetWritable(_R(IDC_SELPOINT), TRUE);
03639         SetGadgetWritable(_R(IDC_SELCOLOUR), TRUE);
03640     }
03641     else
03642     {
03643         SetGadgetHelp(_R(IDC_SELPOINT),  _R(IDBBL_FILLTOOL_FILLHANDLE), _R(IDS_FILLTOOL_FILLHANDLE));
03644         SetGadgetHelp(_R(IDC_SELCOLOUR), _R(IDBBL_FILLTOOL_FILLCOLOUR), _R(IDS_FILLTOOL_FILLCOLOUR));
03645         SetGadgetWritable(_R(IDC_SELPOINT), FALSE);
03646         SetGadgetWritable(_R(IDC_SELCOLOUR), FALSE);
03647     }
03648 
03649 //  ShowCommonTranspType();
03650     ShowCommonTesselate();
03651     ShowCommonEffect();
03652 
03653     if (AttrFillGeometry::SelectionCount == 0)
03654     {
03655         ShowCommonBitmapDpi();
03656         ShowCommonFractalGrain();
03657     }
03658     else
03659     {
03660         ShowControlPointInfo();
03661     }
03662 }
03663 
03664 /********************************************************************************************
03665 
03666 >   void GradInfoBarOp::ShowNoiseInfo()
03667 
03668     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
03669     Created:    20/01/97
03670     Purpose:    Show info on a noise fill.
03671 
03672 ********************************************************************************************/
03673 
03674 void GradInfoBarOp::ShowNoiseInfo()
03675 {
03676     if (OldMode != NOISEFILL)
03677     {   
03678         InitTesselate();
03679         InitEffect();
03680 
03681         SetGadgetHelp(_R(IDC_EFFECT),       _R(IDBBL_FILLTOOL_FILLEFFECT),      _R(IDS_FILLTOOL_FILLEFFECT));
03682         SetGadgetHelp(_R(IDC_MAPPING),      _R(IDBBL_FILLTOOL_FILLTILING),      _R(IDS_FILLTOOL_FILLTILING));
03683     }
03684 
03685     if (AttrFillGeometry::SelectionCount == 0)
03686     {
03687         SetGadgetHelp(_R(IDC_SELPOINT),  _R(IDBBL_FILLTOOL_NOISERES),   _R(IDS_FILLTOOL_NOISERES));
03688         SetGadgetHelp(_R(IDC_SELCOLOUR), _R(IDBBL_FILLTOOL_NOISESCALE), _R(IDS_FILLTOOL_NOISESCALE));
03689         SetGadgetWritable(_R(IDC_SELPOINT), TRUE);
03690         SetGadgetWritable(_R(IDC_SELCOLOUR), TRUE);
03691     }
03692     else
03693     {
03694         SetGadgetHelp(_R(IDC_SELPOINT),  _R(IDBBL_FILLTOOL_FILLHANDLE), _R(IDS_FILLTOOL_FILLHANDLE));
03695         SetGadgetHelp(_R(IDC_SELCOLOUR), _R(IDBBL_FILLTOOL_FILLCOLOUR), _R(IDS_FILLTOOL_FILLCOLOUR));
03696         SetGadgetWritable(_R(IDC_SELPOINT), FALSE);
03697         SetGadgetWritable(_R(IDC_SELCOLOUR), FALSE);
03698     }
03699 
03700     ShowCommonTesselate();
03701     ShowCommonEffect();
03702 
03703     if (AttrFillGeometry::SelectionCount == 0)
03704     {
03705         ShowCommonBitmapDpi();
03706         ShowCommonNoiseScale();
03707     }
03708     else
03709     {
03710         ShowControlPointInfo();
03711     }
03712 }
03713 
03714 /********************************************************************************************
03715 
03716 >   void GradInfoBarOp::ShowCommonType(BOOL ShowDataAndNotSet = TRUE)
03717 
03718     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> (altered by Chris Snook)
03719     Created:    25/8/94
03720     Inputs:     if ShowDataAndNotSet is FALSE, then data members will be set (for controlling
03721                 menu selection logic) and data will not be shown in the relevant control.
03722     Purpose:    Show any Common Fill Type in the selection.
03723 
03724 ********************************************************************************************/
03725 
03726 void GradInfoBarOp::ShowCommonType(BOOL ShowDataAndNotSet)
03727 {
03728     String_64 Str;
03729 
03730     CommonAttr = SelRange::ATTR_NONE;
03731     Str.Load(_R(IDS_FILLTOOL_NONE));
03732 
03733     if (Selection != NULL)
03734     {
03735         Document* pCurrentDoc = Document::GetCurrent();
03736         if (Document::GetSelected())
03737             Document::GetSelected()->SetCurrent();
03738 
03739         // Try and find a common Attribute within the selection.
03740         // All objects in the selection must have an Identical fill for this
03741         // to find anything.
03742         CommonAttr = Selection->FindCommonAttribute(CC_RUNTIME_CLASS(AttrFillGeometry), 
03743                                                     (NodeAttribute**)&CommonGeometry);
03744         CCRuntimeClass* GeometryType;
03745 
03746         // Try and find a common Attribute Type within the selection.
03747         // The fills need not be identical. Just of the same type.
03748         SelRange::CommonAttribResult CommonType = 
03749                 Selection->FindCommonAttributeType(CC_RUNTIME_CLASS(AttrFillGeometry), 
03750                                                    &GeometryType);
03751 
03752         if (CommonAttr == SelRange::ATTR_NONE &&
03753             CommonGeometry != NULL)
03754         {
03755             CommonAttr = SelRange::ATTR_COMMON;
03756         }
03757 
03758         if (CommonType == SelRange::ATTR_NONE &&
03759             GeometryType != NULL)
03760         {
03761             CommonType = SelRange::ATTR_COMMON;
03762         }
03763     
03764         // Make the menu show any Common Fill Type
03765         // or failing that, 'None' or 'Many'.
03766         if (CommonType == SelRange::ATTR_COMMON)
03767         {   
03768             if (GeometryType == CC_RUNTIME_CLASS(AttrFlatColourFill))
03769             {
03770                 Str.Load(_R(IDS_FILLTOOL_FLATFILL));
03771                 Mode = FLATFILL;
03772                 CurrentGeometryIndex = FGMENU_FLAT;
03773             }
03774             else if (GeometryType == CC_RUNTIME_CLASS(AttrLinearColourFill))
03775             {
03776                 Str.Load(_R(IDS_FILLTOOL_LINEAR));
03777                 Mode = GRADFILL;
03778                 CurrentGeometryIndex = FGMENU_LINEAR;
03779             }
03780             else if (GeometryType == CC_RUNTIME_CLASS(AttrCircularColourFill))
03781             {
03782                 Str.Load(_R(IDS_FILLTOOL_CIRCULAR));
03783                 Mode = GRADFILL;
03784                 CurrentGeometryIndex = FGMENU_CIRCULAR;
03785             }
03786             else if (GeometryType == CC_RUNTIME_CLASS(AttrRadialColourFill))
03787             {
03788                 Str.Load(_R(IDS_FILLTOOL_ELLIPTICAL));
03789                 Mode = GRADFILL;
03790                 CurrentGeometryIndex = FGMENU_RADIAL;
03791             }
03792             else if (GeometryType == CC_RUNTIME_CLASS(AttrConicalColourFill))
03793             {
03794                 Str.Load(_R(IDS_FILLTOOL_CONICAL));
03795                 Mode = GRADFILL;
03796                 CurrentGeometryIndex = FGMENU_CONICAL;
03797             }
03798             else if (GeometryType == CC_RUNTIME_CLASS(AttrSquareColourFill))
03799             {
03800                 Str.Load(_R(IDS_FILLTOOL_SQUARE));
03801                 Mode = GRADFILL;
03802                 CurrentGeometryIndex = FGMENU_SQUARE;
03803             }
03804             else if (GeometryType == CC_RUNTIME_CLASS(AttrThreeColColourFill))
03805             {
03806                 Str.Load(_R(IDS_FILLTOOL_THREECOL));
03807                 Mode = GRADREPEATFILL;
03808                 CurrentGeometryIndex = FGMENU_THREECOL;
03809             }
03810             else if (GeometryType == CC_RUNTIME_CLASS(AttrFourColColourFill))
03811             {
03812                 Str.Load(_R(IDS_FILLTOOL_FOURCOL));
03813                 Mode = GRADREPEATFILL;
03814                 CurrentGeometryIndex = FGMENU_FOURCOL;
03815             }
03816             else if (GeometryType == CC_RUNTIME_CLASS(AttrBitmapColourFill))
03817             {
03818                 Str.Load(_R(IDS_FILLTOOL_BITMAP));
03819                 Mode = BITMAPFILL;
03820                 CurrentGeometryIndex = FGMENU_BITMAP;
03821             }
03822             else if (GeometryType == CC_RUNTIME_CLASS(AttrFractalColourFill))
03823             {
03824                 Str.Load(_R(IDS_FILLTOOL_FRACTAL));
03825                 Mode = FRACTALFILL;
03826                 CurrentGeometryIndex = FGMENU_FRACTAL;
03827             }
03828             else if (GeometryType == CC_RUNTIME_CLASS(AttrNoiseColourFill))
03829             {
03830                 Str.Load(_R(IDS_FILLTOOL_NOISE));
03831                 Mode = NOISEFILL;
03832                 CurrentGeometryIndex = FGMENU_NOISE;
03833             }
03834         }
03835         else
03836         {
03837             if (CommonAttr == SelRange::ATTR_MANY)
03838             {
03839                 // There are many different types of fill selected
03840                 Str.Load(_R(IDS_FILLTOOL_MANY));
03841                 Mode = MANYFILLS;
03842                 CurrentGeometryIndex = FGMENU_MANY;
03843             }
03844         }
03845         
03846         if (pCurrentDoc)
03847             pCurrentDoc->SetCurrent();
03848     }
03849 
03850     // Update the Menus
03851     if (ShowDataAndNotSet)
03852     {
03853         SetGadgetString(_R(IDC_GEOMETRY),&Str);
03854     }
03855 }
03856 
03857 
03858 
03859 /********************************************************************************************
03860 
03861 >   void GradInfoBarOp::ShowCommonMapping()
03862 
03863     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com> (altered by Chris Snook)
03864     Created:    22/8/96
03865     Inputs:     if ShowDataAndNotSet is FALSE, then data members will be set (for controlling
03866                 menu selection logic) and data will not be shown in the relevant control.
03867     Purpose:    Show any Common Fill Mapping in the selection.
03868 
03869 ********************************************************************************************/
03870 
03871 void GradInfoBarOp::ShowCommonMapping(BOOL ShowDataAndNotSet)
03872 {
03873     String_64 Str;
03874 
03875     INT32 CommTess = FindCommonTesselate();
03876 
03877     switch (CommTess)
03878     {
03879         case -1:
03880             Str.Load(_R(IDS_FILLTOOL_MANY));
03881             CurrentMappingIndex = -2;//FMMENU_REPEATING;
03882             break;
03883 
03884         case 0:
03885             Str.Load(_R(IDS_FILLTOOL_NONE));
03886             CurrentMappingIndex = -1;//FMMENU_REPEATING;
03887             break;
03888 
03889         case 1:
03890             Str.Load(_R(IDS_FILLTOOL_MAPSIMPLE));
03891             CurrentMappingIndex = FMMENU_SIMPLE;
03892             break;
03893 
03894         case 2:
03895 //Mark Howitt, 8/10/97. If were using the new grad fills and repeat is set to 2, this doesn`t mean repeating
03896 //                      grad fills. Make sure it only shows it as simple! 
03897 #ifdef NEW_FEATURES
03898             if(Mode == GRADFILL)
03899             {
03900                 Str.Load(_R(IDS_FILLTOOL_MAPSIMPLE));
03901                 CurrentMappingIndex = FMMENU_SIMPLE;
03902                 break;
03903             }
03904             else
03905             {
03906                 Str.Load(_R(IDS_FILLTOOL_MAPREPEAT));
03907                 CurrentMappingIndex = FMMENU_REPEATING;
03908                 break;
03909             }
03910         case 4:     // Must be a repeating grad fill!
03911 #endif
03912         case 3:
03913             Str.Load(_R(IDS_FILLTOOL_MAPREPEAT));
03914             CurrentMappingIndex = 2;//FMMENU_REPEATING;
03915             break;
03916     }
03917 
03918     if (ShowDataAndNotSet)
03919     {
03920         SetGadgetString(_R(IDC_MAPPING),&Str);
03921     }
03922 }
03923 
03924 /********************************************************************************************
03925 
03926 >   void GradInfoBarOp::ShowCommonEffect()
03927 
03928     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> (altered by Chris Snook)
03929     Created:    25/8/94
03930     Inputs:     if ShowDataAndNotSet is FALSE, then data members will be set (for controlling
03931                 menu selection logic) and data will not be shown in the relevant control.
03932     Purpose:    Show any Common Fill Type in the selection.
03933 
03934 ********************************************************************************************/
03935 
03936 void GradInfoBarOp::ShowCommonEffect(BOOL ShowDataAndNotSet)
03937 {
03938     String_64 Str;
03939 
03940     CommonAttrEffect = SelRange::ATTR_NONE;
03941     Str.Load(_R(IDS_FILLTOOL_NONE));
03942 
03943     if (Selection != NULL)
03944     {
03945         // Try and find a common Attribute within the selection.
03946         // All objects in the selection must have an Identical fill for this
03947         // to find anything.
03948         CommonAttrEffect = Selection->FindCommonAttribute(CC_RUNTIME_CLASS(AttrFillEffect), 
03949                                                     (NodeAttribute**)&CommonEffect);
03950         CCRuntimeClass* EffectType;
03951 
03952         // Try and find a common Attribute Type within the selection.
03953         // The fills need not be identical. Just of the same type.
03954         SelRange::CommonAttribResult CommonType = 
03955                 Selection->FindCommonAttributeType(CC_RUNTIME_CLASS(AttrFillEffect), 
03956                                                     &EffectType);
03957 
03958         if (CommonAttrEffect == SelRange::ATTR_NONE &&
03959             CommonEffect != NULL)
03960         {
03961             CommonAttrEffect = SelRange::ATTR_COMMON;
03962         }
03963 
03964         if (CommonType == SelRange::ATTR_NONE &&
03965             EffectType != NULL)
03966         {
03967             CommonType = SelRange::ATTR_COMMON;
03968         }
03969     
03970         // Make the menu show any Common Fill Type
03971         // or failing that, 'None' or 'Many'.
03972         if (CommonType == SelRange::ATTR_COMMON)
03973         {   
03974             if (EffectType == CC_RUNTIME_CLASS(AttrFillEffectFade))
03975             {
03976                 Str.Load(_R(IDS_FILLTOOL_FADE));
03977                 CurrentEffectIndex = FEMENU_FADE;
03978             }
03979             else if (EffectType == CC_RUNTIME_CLASS(AttrFillEffectRainbow))
03980             {
03981                 Str.Load(_R(IDS_FILLTOOL_RAINBOW));
03982                 CurrentEffectIndex = FEMENU_RAINBOW;
03983             }
03984             else if (EffectType == CC_RUNTIME_CLASS(AttrFillEffectAltRainbow))
03985             {
03986                 Str.Load(_R(IDS_FILLTOOL_ALTRAINBOW));
03987                 CurrentEffectIndex = FEMENU_ALTRAINBOW;
03988             }
03989         }
03990         else
03991         {
03992             if (CommonType == SelRange::ATTR_MANY)
03993             {
03994                 // There are many different types of fill selected
03995                 Str.Load(_R(IDS_FILLTOOL_MANY));
03996                 CurrentEffectIndex = -1;
03997             }
03998         }
03999     }
04000 
04001     // Update the Menus
04002     if (ShowDataAndNotSet)
04003     {
04004         SetGadgetString(_R(IDC_EFFECT),&Str);
04005     }
04006 }
04007 
04008 
04009 /********************************************************************************************
04010 
04011 >   void GradInfoBarOp::ShowCommonTesselate()
04012 
04013     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
04014     Created:    25/8/94
04015     Purpose:    Show any Common Fill Tesselation in the selection.
04016 
04017 ********************************************************************************************/
04018 
04019 void GradInfoBarOp::ShowCommonTesselate()
04020 {
04021     String_64 Str;
04022 
04023     INT32 CommTess = FindCommonTesselate();
04024 
04025     switch (CommTess)
04026     {
04027         case -1:
04028             Str.Load(_R(IDS_FILLTOOL_MANY));
04029             CurrentMappingIndex = FTMENU_REPEAT;
04030             break;
04031 
04032         case 0:
04033             Str.Load(_R(IDS_FILLTOOL_NONE));
04034             CurrentMappingIndex = FTMENU_REPEAT;
04035             break;
04036 
04037         case 1:
04038             Str.Load(_R(IDS_FILLTOOL_TESS_SIMPLE));
04039             CurrentMappingIndex = FTMENU_SIMPLE;
04040             break;
04041 
04042         case 2:
04043             Str.Load(_R(IDS_FILLTOOL_TESS_REPEAT));
04044             CurrentMappingIndex = FTMENU_REPEAT;
04045             break;
04046 
04047         case 3:
04048             Str.Load(_R(IDS_FILLTOOL_TESS_REPEATINV));
04049             CurrentMappingIndex = FTMENU_REPEATINV;
04050             break;
04051     }
04052 
04053     SetGadgetString(_R(IDC_MAPPING),&Str);
04054     EnableGadget(_R(IDC_MAPPING), TRUE);
04055 }
04056 
04057 /********************************************************************************************
04058 
04059 >   INT32 GradInfoBarOp::FindCommonTesselate()
04060 
04061     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
04062     Created:    25/8/94
04063     Purpose:    Find any Common Fill Tesselation in the selection.
04064 
04065 ********************************************************************************************/
04066 
04067 INT32 GradInfoBarOp::FindCommonTesselate()
04068 {
04069     INT32 CommonTess = 0;
04070     Node* pNode;
04071     NodeAttribute* pChild;
04072 
04073     if (Selection->Count() == 0)
04074     {
04075         AttrFillMapping* pCurrentMapping = GetCurrentMapping();
04076 
04077         if (pCurrentMapping != NULL)
04078         {
04079             return pCurrentMapping->GetRepeat();
04080         }
04081 
04082         return 0;
04083     }
04084 
04085     // Are there any selected Objects ?
04086     if (Selection != NULL)
04087     {
04088         // Find the first Object
04089         pNode = Selection->FindFirst();
04090         while (pNode != NULL)
04091         {
04092             BOOL FoundAttr = ((NodeRenderableInk*)pNode)->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrFillMapping), &pChild);
04093             
04094             if (FoundAttr)
04095             {
04096                 INT32 Tess = ((AttrFillMapping*)pChild)->GetRepeat();
04097 
04098                 if (CommonTess == 0)
04099                     CommonTess = Tess;
04100 
04101                 if (Tess != CommonTess)
04102                 {
04103                     return -1; // Many
04104                 }
04105             }
04106 
04107             pNode = Selection->FindNext(pNode);
04108         }
04109     }
04110 
04111     //if (CommonTess == 0)
04112     //  return RT_Repeating;
04113 
04114     return CommonTess;
04115 }
04116 
04117 /********************************************************************************************
04118 
04119 >   void GradInfoBarOp::ShowCommonBitmapName()
04120 
04121     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
04122     Created:    25/8/94
04123     Purpose:    Show any Common Bitmap Name in the selection.
04124 
04125 ********************************************************************************************/
04126 
04127 void GradInfoBarOp::ShowCommonBitmapName()
04128 {
04129     String_64 strName = FindCommonBitmapName();
04130     m_oBitmapDropDown.SelectByLabel(strName);
04131 }
04132 
04133 /********************************************************************************************
04134 
04135 >   String_256 GradInfoBarOp::FindCommonBitmapName()
04136 
04137     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
04138     Created:    25/8/94
04139     Purpose:    Find any Common Bitmap Name in the selection.
04140 
04141 ********************************************************************************************/
04142 
04143 String_256 GradInfoBarOp::FindCommonBitmapName()
04144 {
04145     String_256 CommonName;
04146     CommonName.Load(_R(IDS_FILLTOOL_NONE));
04147 
04148     String_256 Name;
04149     Name.Load(_R(IDS_FILLTOOL_NONE));
04150     
04151     String_256 None;
04152     None.Load(_R(IDS_FILLTOOL_NONE));
04153 
04154     String_256 Many;
04155     Many.Load(_R(IDS_FILLTOOL_MANY));
04156 
04157     if (Selection->Count() == 0)
04158     {
04159         AttrFillGeometry* pCurrentFill = GetCurrentGeometry();
04160 
04161         if (pCurrentFill && pCurrentFill->IsABitmapFill())
04162         {
04163             KernelBitmap* pBitmap = pCurrentFill->GetBitmap();
04164             if (pBitmap)
04165             {
04166                 OILBitmap* pOilBitmap = pBitmap->ActualBitmap;
04167                 if (pOilBitmap)
04168                 {
04169                     return pOilBitmap->GetName();
04170                 }
04171             }
04172         }
04173 
04174         return None;
04175     }
04176 
04177     // Find the first Fill Attribute in the selection
04178     AttrFillGeometry* pAttrNode = AttrFillGeometry::FindFirstSelectedAttr();
04179 
04180     // Return if there aren't any
04181     if (pAttrNode == NULL)
04182         return None;
04183 
04184     while (pAttrNode != NULL)
04185     {
04186         if (pAttrNode->IsKindOf(CC_RUNTIME_CLASS(AttrBitmapColourFill)))
04187         {
04188             Name = None;
04189             KernelBitmap* pBitmap = pAttrNode->GetBitmap();
04190             if (pBitmap)
04191             {
04192                 OILBitmap* pOilBitmap = pBitmap->ActualBitmap;
04193                 if (pOilBitmap)
04194                 {
04195                     Name = pOilBitmap->GetName();
04196                 }
04197             }
04198 
04199             if (CommonName == None)
04200                 CommonName = Name;
04201 
04202             if (Name != CommonName)
04203             {
04204                 return Many;
04205             }
04206         }
04207 
04208         // Check the next fill
04209         pAttrNode = AttrFillGeometry::FindNextSelectedAttr();
04210     }
04211 
04212     return CommonName;
04213 }
04214 
04215 /********************************************************************************************
04216 
04217 >   void GradInfoBarOp::ShowCommonBitmapDpi()
04218 
04219     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
04220     Created:    25/8/94
04221     Purpose:    Show any Common Bitmap Dpi in the selection.
04222 
04223 ********************************************************************************************/
04224 
04225 void GradInfoBarOp::ShowCommonBitmapDpi()
04226 {
04227     INT32 dpi = FindCommonBitmapDpi();
04228 
04229     String_64 DpiStr;
04230 
04231     if (dpi == 0)
04232     {
04233         DpiStr.Load(_R(IDS_FILLTOOL_NODPI));
04234     }
04235 
04236     if (dpi == -1)
04237     {
04238         DpiStr.Load(_R(IDS_FILLTOOL_MANYDPI));
04239     }
04240 
04241     if (dpi > 0)
04242     {
04243         // use the conversion functions rather than trying to do it ourselves
04244         Convert::LongToString(dpi, &DpiStr);
04245         DpiStr += String_64(_R(IDS_FILLTOOL_DPI));
04246     }
04247 
04248     SetGadgetString(_R(IDC_SELPOINT),&DpiStr);
04249     SetGadgetWritable(_R(IDC_SELPOINT), TRUE);
04250 }
04251 
04252 /********************************************************************************************
04253 
04254 >   void GradInfoBarOp::SetGadgetWritable(INT32 id, BOOL enable)
04255 
04256     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
04257     Created:    15/11/94
04258     Inputs:     id, the 'IDC_?' of the control.
04259                 enable, TRUE to allow the control to be typed into. FALSE to make it
04260                         read only.
04261     Purpose:    Sets the state of the 'Read Only' flag of an edit field or combo box.
04262 
04263 ********************************************************************************************/
04264 
04265 void GradInfoBarOp::SetGadgetWritable(INT32 id, BOOL enable)
04266 {
04267     PORTNOTETRACE("other","GradInfoBarOp::SetGadgetWritable - disabled");
04268 #ifndef EXCLUDE_FROM_XARALX
04269     // Get the window handle of the gadget, from the gadget ID
04270     HWND gadget = ::GetDlgItem(WindowID, id);
04271 
04272     // See if it's got a child window (it may be a Combo Box)
04273     HWND hEdit = ::ChildWindowFromPoint(gadget, CPoint(1,1));
04274 
04275     if (hEdit)              // Was there a child window ?
04276         gadget = hEdit;     // Yes, so send the message to it
04277 
04278     if (enable)
04279     {
04280         ::SendMessage(gadget, EM_SETREADONLY, FALSE, 0);    // Clear the Read Only Flag
04281     }
04282     else
04283     {
04284         ::SendMessage(gadget, EM_SETREADONLY, TRUE, 0);     // Set the Read Only Flag
04285     }
04286 #endif
04287 }
04288 
04289 /********************************************************************************************
04290 
04291 >   BOOL GradInfoBarOp::GetGadgetWritable(INT32 id)
04292 
04293     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
04294     Created:    6/11/99
04295     Inputs:     id, the 'IDC_?' of the control.
04296     Returns:    TRUE if writable, FALSE otherwise
04297     Purpose:    Returns whether the control is writable (i.e.  read only, or not).
04298                 void GradInfoBarOp::EnableControls() needs to make use of this to control
04299                 its 'dynamic' toolbar correctly (both of which were also written by me).
04300 
04301 ********************************************************************************************/
04302 
04303 BOOL GradInfoBarOp::GetGadgetWritable (INT32 id)
04304 {
04305     PORTNOTETRACE("other","GradInfoBarOp::SetGadgetWritable - disabled");
04306 #ifndef EXCLUDE_FROM_XARALX
04307     // Get the window handle of the gadget, from the gadget ID
04308     HWND gadget = ::GetDlgItem (WindowID, id);
04309 
04310     // See if it's got a child window (it may be a Combo Box)
04311     HWND hEdit = ::ChildWindowFromPoint (gadget, CPoint(1,1));
04312 
04313     if (hEdit)              // Was there a child window ?
04314         gadget = hEdit;     // Yes, so send the message to it
04315 
04316     if (GetWindowLong (gadget, GWL_STYLE) & ES_READONLY)
04317     {
04318         return (TRUE);
04319     }
04320     else
04321     {
04322         return (FALSE);
04323     }
04324 #else
04325     return TRUE;
04326 #endif
04327 }
04328 
04329 /********************************************************************************************
04330 
04331 >   INT32 GradInfoBarOp::FindCommonBitmapDpi()
04332 
04333     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
04334     Created:    25/8/94
04335     Purpose:    Find any Common Bitmap Dpi in the selection.
04336 
04337 ********************************************************************************************/
04338 
04339 INT32 GradInfoBarOp::FindCommonBitmapDpi()
04340 {
04341     if (Selection->Count() == 0)
04342     {
04343         AttrFillGeometry* pCurrentFill = GetCurrentGeometry();
04344 
04345         if (pCurrentFill && pCurrentFill->IsABitmapFill())
04346         {
04347             return pCurrentFill->GetDPI();
04348         }
04349 
04350         return 0;
04351     }
04352 
04353     // Find the first Fill Attribute in the selection
04354     AttrFillGeometry* pAttrNode = AttrFillGeometry::FindFirstSelectedAttr();
04355 
04356     // Return if there aren't any
04357     if (pAttrNode == NULL)
04358         return 0;
04359 
04360     INT32 CommonDpi = 0;
04361     INT32 Dpi = 0;
04362 
04363     while (pAttrNode != NULL)
04364     {
04365         if (pAttrNode->IsKindOf(CC_RUNTIME_CLASS(AttrBitmapFill)))
04366         {
04367             if (pAttrNode->IsKindOf(CC_RUNTIME_CLASS(AttrTextureColourFill)) ||
04368                 pAttrNode->IsKindOf(CC_RUNTIME_CLASS(AttrBitmapColourFill))  )
04369             {
04370                 Dpi = pAttrNode->GetDPI();
04371 
04372                 if (CommonDpi == 0)
04373                     CommonDpi = Dpi;
04374 
04375                 if (Dpi != CommonDpi)
04376                 {
04377                     return -1; // Many
04378                 }
04379             }
04380         }
04381 
04382         // Check the next fill
04383         pAttrNode = AttrFillGeometry::FindNextSelectedAttr();
04384     }
04385 
04386     return CommonDpi;
04387 }
04388 
04389 
04390 /********************************************************************************************
04391 
04392 >   void GradInfoBarOp::ShowCommonFractalGrain()
04393 
04394     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
04395     Created:    25/8/94
04396     Purpose:    Show any Common Fractal Graininess in the selection.
04397 
04398 ********************************************************************************************/
04399 
04400 void GradInfoBarOp::ShowCommonFractalGrain()
04401 {
04402     double Grain = FindCommonFractalGrain();
04403 
04404     String_64 GrainStr;
04405 
04406     if (Grain == 0)
04407         GrainStr.Load(_R(IDS_FILLTOOL_NOGRAIN));
04408     if (Grain == -1)
04409         GrainStr.Load(_R(IDS_FILLTOOL_MANYGRAIN));
04410     if (Grain > 0)
04411         Convert::DoubleToString(Grain, &GrainStr, 1);
04412 
04413     SetGadgetString(_R(IDC_SELCOLOUR),&GrainStr);
04414     SetGadgetWritable(_R(IDC_SELCOLOUR), TRUE);
04415 }
04416 
04417 /********************************************************************************************
04418 
04419 >   FIXED16 GradInfoBarOp::FindCommonFractalGrain()
04420 
04421     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
04422     Created:    25/8/94
04423     Purpose:    Find any Common Fractal Graininess in the selection.
04424 
04425 ********************************************************************************************/
04426 
04427 double GradInfoBarOp::FindCommonFractalGrain()
04428 {
04429     if (Selection->Count() == 0)
04430     {
04431         AttrFillGeometry* pCurrentFill = GetCurrentGeometry();
04432 
04433         if (pCurrentFill && pCurrentFill->IsAFractalFill())
04434         {
04435             return ((FractalFillAttribute*)pCurrentFill->GetAttributeValue())->Graininess.MakeDouble();
04436         }
04437 
04438         return 0;
04439     }
04440 
04441     // Find the first Fill Attribute in the selection
04442     AttrFillGeometry* pAttrNode = AttrFillGeometry::FindFirstSelectedAttr();
04443 
04444     // Return if there aren't any
04445     if (pAttrNode == NULL)
04446         return 0;
04447 
04448     double CommonGrain = 0;
04449 
04450     while (pAttrNode != NULL)
04451     {
04452         if (pAttrNode->IsKindOf(CC_RUNTIME_CLASS(AttrFractalColourFill)))
04453         {
04454             double Grain = ((FractalFillAttribute*)pAttrNode->GetAttributeValue())->Graininess.MakeDouble();
04455 
04456             if (CommonGrain == 0)
04457                 CommonGrain = Grain;
04458 
04459             if (Grain != CommonGrain)
04460             {
04461                 return -1; // Many
04462             }
04463         }
04464 
04465         // Check the next fill
04466         pAttrNode = AttrFillGeometry::FindNextSelectedAttr();
04467     }
04468 
04469     return CommonGrain;
04470 }
04471 
04472 /********************************************************************************************
04473 
04474 >   void GradInfoBarOp::ShowCommonNoiseScale()
04475 
04476     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
04477     Created:    20/01/97
04478     Purpose:    Show any Common Noise scale in the selection
04479 
04480 ********************************************************************************************/
04481 
04482 void GradInfoBarOp::ShowCommonNoiseScale()
04483 {
04484     double Scale = FindCommonNoiseScale();
04485 
04486     String_64 ScaleStr;
04487 
04488     if (Scale == 0)  
04489         ScaleStr.Load(_R(IDS_FILLTOOL_NOGRAIN));            // evaluates to 'None'
04490     if (Scale == -1) 
04491         ScaleStr.Load(_R(IDS_FILLTOOL_MANYGRAIN));          // evaluates to 'Many'
04492     if (Scale > 0)   
04493         Convert::DoubleToString(Scale, &ScaleStr, 1);
04494 
04495     SetGadgetString(_R(IDC_SELCOLOUR),&ScaleStr);
04496     SetGadgetWritable(_R(IDC_SELCOLOUR), TRUE);
04497 }
04498 
04499 /********************************************************************************************
04500 
04501 >   double GradInfoBarOp::FindCommonNoiseScale()
04502 
04503     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
04504     Created:    20/01/97
04505     Purpose:    Find any common noise scale in the selection.
04506 
04507 ********************************************************************************************/
04508 
04509 double GradInfoBarOp::FindCommonNoiseScale()
04510 {
04511     if (Selection->Count() == 0)
04512     {
04513         AttrFillGeometry* pCurrentFill = GetCurrentGeometry();
04514 
04515         if (pCurrentFill && IS_A(pCurrentFill, AttrNoiseColourFill))
04516         {
04517             return ((NoiseFillAttribute*)pCurrentFill->GetAttributeValue())->GetGraininess().MakeDouble();
04518         }
04519 
04520         return 0;
04521     }
04522 
04523     // Find the first Fill Attribute in the selection
04524     AttrFillGeometry* pAttrNode = AttrFillGeometry::FindFirstSelectedAttr();
04525 
04526     // Return if there aren't any
04527     if (pAttrNode == NULL)
04528         return 0;
04529 
04530     double CommonScale = 0;
04531 
04532     while (pAttrNode != NULL)
04533     {
04534         if (pAttrNode->IsKindOf(CC_RUNTIME_CLASS(AttrNoiseColourFill)))
04535         {
04536             double Scale = ((NoiseFillAttribute*)pAttrNode->GetAttributeValue())->GetGraininess().MakeDouble();
04537 
04538             if (CommonScale == 0)
04539                 CommonScale = Scale;
04540 
04541             if (Scale != CommonScale)
04542             {
04543                 return -1; // Many
04544             }
04545         }
04546 
04547         // Check the next fill
04548         pAttrNode = AttrFillGeometry::FindNextSelectedAttr();
04549     }
04550 
04551     return CommonScale;
04552 }
04553 
04554 /********************************************************************************************
04555 
04556 >   void GradInfoBarOp::ShowControlPointInfo()
04557 
04558     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
04559     Created:    3/8/94
04560     Purpose:    Show Info about selected control points.
04561 
04562 ********************************************************************************************/
04563 
04564 void GradInfoBarOp::ShowControlPointInfo()
04565 {
04566     String_64 PointStr;
04567     String_64 ColourStr;
04568 
04569     // Look though the selection for any selected control points
04570     ScanSelectionForControlPoints(&PointStr, &ColourStr);
04571 
04572     // PointStr and ColourStr will be updated if we find any
04573 
04574     // Show the selected control points state
04575     SetStringGadgetValue(_R(IDC_SELPOINT), PointStr);
04576     SetStringGadgetValue(_R(IDC_SELCOLOUR), ColourStr);
04577 
04578     if ((Mode != BITMAPFILL && 
04579          Mode != FRACTALFILL && 
04580          Mode != NOISEFILL ) || AttrFillGeometry::SelectionCount > 0)
04581     {
04582         SetGadgetString(_R(IDC_SELPOINT),&PointStr);
04583     }
04584 
04585     SetGadgetString(_R(IDC_SELCOLOUR),&ColourStr);
04586 }
04587 
04588 /********************************************************************************************
04589 
04590 >   void GradInfoBarOp::ScanSelectionForControlPoints(String_64* PointString, 
04591                                                         String_64* ColourString)
04592     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
04593     Created:    3/8/94
04594     Purpose:    Look for selected control points within the selection.
04595 
04596 ********************************************************************************************/
04597 
04598 void GradInfoBarOp::ScanSelectionForControlPoints(String_64* PointString, 
04599                                                   String_64* ColourString)
04600 {
04601     *PointString = _T("");
04602     *ColourString = _T("");
04603 
04604     AttrFillGeometry* pAttrNode;
04605     UINT32 count = Selection->Count();
04606 
04607     // Find the first Fill Attribute in the selection
04608     if (count == 0)
04609     {
04610         pAttrNode = GetCurrentGeometry();
04611     }
04612     else
04613     {
04614         pAttrNode = AttrFillGeometry::FindFirstSelectedAttr();
04615     }
04616 
04617     AllowForceToSimpleMapping = TRUE;
04618     
04619     // Return if there aren't any
04620     if (pAttrNode == NULL)
04621     {
04622         (*PointString).Load(_R(IDS_FILLTOOL_NONE));
04623         (*ColourString).Load(_R(IDS_FILLTOOL_NONE));
04624         return;
04625     }
04626     
04627     INT32 SelCount = 0;
04628     BOOL CommonColour = TRUE;
04629     BOOL CommonPoint  = TRUE;
04630 
04631     BOOL AllFlat = TRUE;
04632     BOOL AnyNeedSimple = FALSE;
04633 
04634     while (pAttrNode != NULL)
04635     {
04636         if (AttrFillGeometry::FillSelectionCount() > 0)
04637         {
04638             if (!(pAttrNode->GetRuntimeClass() == CC_RUNTIME_CLASS(AttrFlatColourFill)))
04639             {
04640                 // Get the selection state and colours of this fill
04641                 String_64 PointStr = GetSelectedPoint(pAttrNode);
04642                 String_64 ColourStr = GetSelectedColour(pAttrNode);
04643 
04644                 String_64 Str;
04645                 Str.Load(_R(IDS_FILLTOOL_NONE));
04646 
04647                 // Where there any points selected ?
04648                 if (PointStr != Str)
04649                 {
04650                     // Update and keep a count
04651                     *PointString = PointStr;
04652                     SelCount++;
04653 
04654                     if (*PointString == String_64(_T("")))
04655                         *PointString = PointStr;
04656 
04657                     if (*PointString != PointStr)
04658                         CommonPoint = FALSE;
04659 
04660                     if (*ColourString == String_64(_T("")))
04661                         *ColourString = ColourStr;
04662 
04663                     if (*ColourString != ColourStr)
04664                         CommonColour = FALSE;
04665     
04666                     AllFlat = FALSE;
04667                 }
04668             }
04669         }
04670         else 
04671         {
04672             if (pAttrNode->GetRuntimeClass() == CC_RUNTIME_CLASS(AttrFlatColourFill))
04673             {
04674                 if ( pAttrNode->GetStartColour() != NULL )
04675                 {
04676                     (*PointString).Load(_R(IDS_FILLTOOL_FLATFILL));
04677 
04678                     if (*ColourString == String_64(_T("")))
04679                         *ColourString = GetColourName(*pAttrNode->GetStartColour());
04680 
04681                     if (*ColourString != GetColourName(*pAttrNode->GetStartColour()))
04682                         CommonColour = FALSE;
04683 
04684                     SelCount++;
04685                 }
04686             }
04687             else
04688             {
04689                 if (SelCount > 0)
04690                     AllFlat = FALSE;
04691             }
04692         }
04693 
04694         // If this is a colour fill attribute and doesn't need simple mapping then set FALSE
04695         if (pAttrNode->IsAColourFill() && pAttrNode->NeedsForceToSimpleMapping())
04696             AnyNeedSimple = TRUE;
04697             
04698         // Check the next fill
04699         if (count > 0)
04700             pAttrNode = AttrFillGeometry::FindNextSelectedAttr();
04701         else
04702             pAttrNode = NULL;
04703     }
04704 
04705     if (AnyNeedSimple)
04706         AllowForceToSimpleMapping = FALSE;
04707 
04708     if (AttrFillGeometry::FillSelectionCount() == 0 && !AllFlat)
04709     {
04710         (*PointString).Load(_R(IDS_FILLTOOL_MANY));
04711     }
04712 
04713     if (SelCount == 0)
04714     {
04715         (*PointString).Load(_R(IDS_FILLTOOL_NONE));
04716         (*ColourString).Load(_R(IDS_FILLTOOL_NONE));
04717     }
04718 
04719     // Was there more than one fill with points selected ?
04720     if (!CommonPoint)
04721     {
04722         // Status indicating many points selected
04723         (*PointString).Load(_R(IDS_FILLTOOL_MANY));
04724     }
04725 
04726     if (!CommonColour)
04727     {
04728         (*ColourString).Load(_R(IDS_FILLTOOL_MANY));
04729     }
04730 
04731 /*
04732     *PointString = "";
04733     *ColourString = "";
04734 
04735     // Find the first Fill Attribute in the selection
04736     AttrFillGeometry* pAttrNode = AttrFillGeometry::FindFirstSelectedAttr();
04737 
04738     // Return if there aren't any
04739     if (pAttrNode == NULL)
04740         return;
04741     
04742     INT32 SelCount = 0;
04743     BOOL CommonPoint = TRUE;
04744     BOOL CommonColour = TRUE;
04745 
04746     while (pAttrNode != NULL)
04747     {
04748         // Get the selection state and colours of this fill
04749         String_64 PointStr = GetSelectedPoint(pAttrNode);
04750         String_64 ColourStr = GetSelectedColour(pAttrNode);
04751 
04752         // Where there any points selected ?
04753         String_64 Str;
04754         Str.Load(_R(IDS_FILLTOOL_NONE));
04755 
04756         if (PointStr != Str)
04757         {
04758             if (*PointString == String_64(""))
04759             {
04760                 // Update and keep a count
04761                 *PointString = PointStr;
04762                 *ColourString = ColourStr;
04763                 SelCount++;
04764             }                   
04765             else
04766             {
04767                 if (CommonPoint && *PointString != PointStr)
04768                 {
04769                     CommonPoint = FALSE;
04770                     (*PointString).Load(_R(IDS_FILLTOOL_MANY));
04771                 }
04772 
04773                 if (CommonColour && *ColourString != ColourStr)
04774                 {
04775                     CommonColour = FALSE;
04776                     (*ColourString).Load(_R(IDS_FILLTOOL_MANY));
04777                 }
04778             }
04779         
04780             if (!CommonPoint && !CommonColour)
04781                 return;
04782         }
04783 
04784         // Check the next fill
04785         pAttrNode = AttrFillGeometry::FindNextSelectedAttr();
04786     }
04787 
04788     if (SelCount == 0)
04789     {
04790         (*PointString).Load(_R(IDS_FILLTOOL_NONE));
04791         (*ColourString).Load(_R(IDS_FILLTOOL_NONE));
04792     }
04793 */
04794 }
04795 
04796 /********************************************************************************************
04797 
04798 >   String_64 GradInfoBarOp::GetSelectedPoint(AttrFillGeometry* pGeometry)
04799 
04800     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
04801     Created:    9/8/94
04802     Inputs:     -
04803     Outputs:    -
04804     Returns:    A String_64, "None", "Many", or "Start Colour", "End Colour" etc.
04805     Purpose:    Gets a textual description of a fills contol point selection state.
04806 
04807 ********************************************************************************************/
04808 
04809 String_64 GradInfoBarOp::GetSelectedPoint(AttrFillGeometry* pGeometry)
04810 {
04811     String_64 Str;
04812 
04813     // how many happen to be selected at the moment?
04814     UINT32 SelCount = pGeometry->GetSelectionCount();
04815 
04816     // if there's nothing selected then we're done
04817     if (SelCount<1)
04818     {
04819         Str.Load(_R(IDS_FILLTOOL_NONE));
04820         return Str;
04821     }
04822 
04823     // more than one?   
04824     if (SelCount>1)
04825     {
04826         Str.Load(_R(IDS_FILLTOOL_MANY));
04827         return Str;
04828     }
04829 
04830     // ramp blobs have negative indexes
04831     INT32 i = pGeometry->GetFirstSelectedIndex();
04832     if (ISA_RAMPINDEX(i))
04833     {
04834         Str.Load(_R(IDS_FILLTOOL_RAMPCOL));
04835         return Str;
04836     }
04837 
04838     // ok its an end blob so which one is it?
04839     switch (i)
04840     {
04841         case FILLCONTROL_STARTPOINT:
04842             Str.Load(_R(IDS_FILLTOOL_STARTCOL));
04843             break;
04844 
04845         case FILLCONTROL_ENDPOINT:
04846         case FILLCONTROL_SECONDARYPOINT:
04847             Str.Load(_R(IDS_FILLTOOL_ENDCOL));
04848             break;
04849 
04850         case FILLCONTROL_ENDPOINT2:
04851             Str.Load(_R(IDS_FILLTOOL_ENDCOL2));
04852             break;
04853 
04854         case FILLCONTROL_ENDPOINT3:
04855             Str.Load(_R(IDS_FILLTOOL_ENDCOL3));
04856             break;
04857         
04858         default:
04859             Str.Load(_R(IDS_FILLTOOL_NONE));
04860             break;
04861     }
04862 
04863     return Str;
04864 }
04865 
04866 /*
04867 String_64 GradInfoBarOp::GetSelectedPoint(AttrFillGeometry* pGeometry)
04868 {
04869     BOOL SelState[5];
04870     String_64 Str;
04871 
04872     // Get the selection state of this fills control points
04873     pGeometry->GetSelectionState(SelState, 5);
04874 
04875     INT32 SelCount = 0;
04876     for (INT32 i=0; i<5; i++)
04877     {
04878         // Is this point selected ?
04879         if (SelState[i])
04880         {
04881             // Get a description of the Point
04882             switch (i)
04883             {
04884                 case FILLCONTROL_STARTPOINT:
04885                     Str.Load(_R(IDS_FILLTOOL_STARTCOL));
04886                     break;
04887 
04888                 case FILLCONTROL_ENDPOINT:
04889                     Str.Load(_R(IDS_FILLTOOL_ENDCOL));
04890                     break;
04891 
04892                 case FILLCONTROL_ENDPOINT2:
04893                     Str.Load(_R(IDS_FILLTOOL_ENDCOL2));
04894                     break;
04895 
04896                 case FILLCONTROL_ENDPOINT3:
04897                     Str.Load(_R(IDS_FILLTOOL_ENDCOL3));
04898                     break;
04899 
04900                 case FILLCONTROL_SECONDARYPOINT:
04901                     Str.Load(_R(IDS_FILLTOOL_ENDCOL));
04902                     break;
04903 
04904             }
04905             // Keep a count of how many points were selected
04906             SelCount++;
04907         }
04908     }
04909 
04910     if (SelCount == 0)
04911         Str.Load(_R(IDS_FILLTOOL_NONE));    // No control points were selected
04912 
04913     if (SelCount > 1)
04914         Str.Load(_R(IDS_FILLTOOL_MANY));    // Many control points were selected
04915 
04916     return Str;
04917 }
04918 */
04919 
04920 /********************************************************************************************
04921 
04922 >   String_64 GradInfoBarOp::GetSelectedColour(AttrFillGeometry* pGeometry)
04923 
04924     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
04925     Created:    9/8/94
04926     Inputs:     -
04927     Outputs:    -
04928     Returns:    A String_64, "None", "Many", or "Colour Name".
04929     Purpose:    Gets a textual description of a fills contol point colour.
04930 
04931 ********************************************************************************************/
04932 
04933 String_64 GradInfoBarOp::GetSelectedColour(AttrFillGeometry* pGeometry)
04934 {
04935     String_64 Str;
04936 
04937     // fill the string with nothing at the moment
04938     Str.Load(_R(IDS_FILLTOOL_NONE));
04939     // how many happen to be selected at the moment?
04940     UINT32 SelCount = pGeometry->GetSelectionCount();
04941     
04942     // if there's nothing selected then we're done
04943     if (SelCount<1)
04944         return Str;
04945 
04946     // single selected end point?
04947     if (SelCount==1)
04948     {
04949         // then find the name of the colour
04950         DocColour *pColour = pGeometry->GetFirstSelectedColour();
04951         if (pColour)
04952             Str=GetColourName(*pColour);
04953         return Str; 
04954     }
04955 
04956     // more that one selected blob so go figure.
04957     Str.Load(_R(IDS_FILLTOOL_MANY));
04958     return Str;
04959 }
04960 
04961 /*
04962 String_64 GradInfoBarOp::GetSelectedColour(AttrFillGeometry* pGeometry)
04963 {
04964     BOOL SelState[5];
04965     String_64 Str;
04966 
04967     // Get the selection state of this fills control points
04968     pGeometry->GetSelectionState(SelState, 5);
04969 
04970     INT32 SelCount = 0;
04971     for (INT32 i=0; i<5; i++)
04972     {
04973         // Is this point selected ?
04974         if (SelState[i])
04975         {
04976             // Get a description of the Points Colour
04977             switch (i)
04978             {
04979                 case FILLCONTROL_STARTPOINT:
04980                     if (pGeometry->GetStartColour())
04981                         Str = GetColourName(*(pGeometry->GetStartColour()));
04982                     else
04983                         Str.Load(_R(IDS_FILLTOOL_NONE));
04984                     break;
04985 
04986                 case FILLCONTROL_ENDPOINT:
04987                 case FILLCONTROL_SECONDARYPOINT:
04988                     if (pGeometry->GetEndColour())
04989                         Str = GetColourName(*(pGeometry->GetEndColour()));
04990                     else
04991                         Str.Load(_R(IDS_FILLTOOL_NONE));
04992                     break;
04993 
04994                 case FILLCONTROL_ENDPOINT2:
04995                     if (pGeometry->GetEndColour2())
04996                         Str = GetColourName(*(pGeometry->GetEndColour2()));
04997                     else
04998                         Str.Load(_R(IDS_FILLTOOL_NONE));
04999                     break;
05000 
05001                 case FILLCONTROL_ENDPOINT3:
05002                     if (pGeometry->GetEndColour3())
05003                         Str = GetColourName(*(pGeometry->GetEndColour3()));
05004                     else
05005                         Str.Load(_R(IDS_FILLTOOL_NONE));
05006                     break;
05007             }
05008             // Keep a count of how many points were selected
05009             SelCount++;
05010         }
05011     }
05012 
05013     if (SelCount == 0)
05014         Str.Load(_R(IDS_FILLTOOL_NONE));
05015 
05016     if (SelCount > 1)
05017         Str.Load(_R(IDS_FILLTOOL_MANY));
05018 
05019     return Str;
05020 }
05021 */
05022 
05023 /********************************************************************************************
05024 
05025 >   String_64 GradInfoBarOp::GetColourName(DocColour Col)
05026 
05027     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
05028     Created:    9/8/94
05029     Inputs:     -
05030     Returns:    -
05031     Purpose:    Gets a name of a colour.
05032     SeeAlso:    -
05033 
05034 ********************************************************************************************/
05035 
05036 String_64 GradInfoBarOp::GetColourName(DocColour &Col)
05037 {
05038     String_64 Str;
05039     Str.Load(_R(IDS_FILLTOOL_NONE));
05040 
05041     IndexedColour* IndexCol = Col.FindParentIndexedColour();
05042 
05043     // Is this an Index Colour ?
05044     if (IndexCol != NULL)
05045     {
05046         // Yep, so get it's name
05047         Str = *(IndexCol->GetName());
05048     }
05049     else
05050     {
05051         // Check for a colour that we know about
05052         if (Col == COLOUR_NONE)
05053         {
05054             Str.Load(_R(IDS_FILLTOOL_NOCOLOUR));
05055         }
05056         else if (Col == COLOUR_WHITE)
05057         {
05058             Str.Load(_R(IDS_FILLTOOL_WHITE));
05059         }
05060         else if (Col == COLOUR_BLACK)
05061         {
05062             Str.Load(_R(IDS_FILLTOOL_BLACK));
05063         }
05064         else
05065         {
05066 //          Str.Load(_R(IDS_FILLTOOL_LOCAL));
05067             Str.Load(_R(IDS_FILLTOOL_LOCALCOLOUR));
05068         }
05069     }
05070 
05071     return Str;
05072 }
05073 
05074 /********************************************************************************************
05075 
05076 >   void GradInfoBarOp::EnableControls()
05077 
05078     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> (rewritten by Chris Snook)
05079     Created:    3/8/94
05080     Inputs:     -
05081     Outputs:    -
05082     Returns:    -
05083     Purpose:    Enables or disables the controls depending on the current context, i.e.
05084                 the controls are disabled if there is no selection, etc.
05085                 Actually more complicated than this now, cause my function calls now hide/show
05086                 various controls; and dynamically reshuffle the infobar.
05087 
05088 ********************************************************************************************/
05089 
05090 void GradInfoBarOp::EnableControls()
05091 {
05092     if (Document::GetSelected() == NULL)
05093     {   
05094         EnableGadget(_R(IDC_GEOMETRY),      FALSE);
05095         EnableGadget(_R(IDC_MAPPING),       FALSE);
05096         EnableGadget(_R(IDC_EFFECT),        FALSE);
05097         EnableGadget(_R(IDC_SELPOINT),      FALSE);
05098         EnableGadget(_R(IDC_BITMAPEFFECT),  FALSE);
05099         EnableGadget(_R(IDC_BIASGAIN),      FALSE);
05100         EnableGadget(_R(IDC_SELCOLOUR),     FALSE);
05101         
05102         //HideDisableGadgetAndResuffleBar (GetDlgItem ((HWND) GetReadWriteWindowID (), _R(IDC_BITMAPEFFECT)));
05103         //HideDisableGadgetAndResuffleBar (GetDlgItem ((HWND) GetReadWriteWindowID (), _R(IDC_BIASGAIN)));
05104         //HideDisableGadgetAndResuffleBar (GetDlgItem ((HWND) GetReadWriteWindowID (), _R(IDC_SELCOLOUR)));
05105     }
05106     else
05107     {
05108         EnableGadget (_R(IDC_GEOMETRY), TRUE);
05109 
05110         if (Mode != BITMAPFILL) { EnableGadget(_R(IDC_BITMAPEFFECT), FALSE); }
05111         
05112         if ((Mode != FRACTALFILL) && (Mode != NOISEFILL)) { EnableGadget(_R(IDC_SELCOLOUR), FALSE); }
05113 
05114         // fill profile exceptions ....
05115 
05116         BOOL EnableBiasGain = TRUE;     // only for fills that have not been multistage!
05117         BOOL EnableBiasGain2 = FALSE;   // only for bitmap fills that are not contoned!
05118         BOOL EnableAffect = FALSE;      // only for bitmap fills that are not contoned!
05119 
05120         List FillList;
05121 //      FillTools::BuildListOfSelectedNodes(&FillList, CC_RUNTIME_CLASS(AttrFillGeometry));
05122 //      FillTools::BuildListOfSelectedAttrs(&FillList, CC_RUNTIME_CLASS(AttrFillGeometry));
05123         FillTools::GetSelectedAttrList(&FillList, CC_RUNTIME_CLASS(AttrFillGeometry), TRUE, FALSE);
05124 
05125         AttrFillGeometry* pNodeFill = NULL;
05126 
05127         if (!(FillList.IsEmpty()))
05128         {
05129             NodeListItem * pItem = (NodeListItem *)FillList.GetHead();
05130 
05131             while (pItem)
05132             {
05133                 pNodeFill = (AttrFillGeometry*) pItem->pNode;
05134 
05135                 // firstly check for multistage fills ....
05136                 
05137                 if (pNodeFill->GetFillRamp () != NULL)
05138                 {
05139                 //  if (pNodeFill->GetFillRamp ()->GetCount () > 0)
05140                 //  {
05141                         EnableBiasGain = FALSE;     // only for fills that have not been multistaged!
05142                 //  }
05143                 }
05144 
05145                 // secondly check for a contoned bitmap fill
05146                 
05147                 if ((pNodeFill->IsABitmapFill ()) && (pNodeFill->GetStartColour () != NULL) && (pNodeFill->GetEndColour () != NULL))
05148                 {
05149                     EnableBiasGain2 = TRUE;
05150                     EnableAffect = TRUE;
05151                 }
05152             
05153                 pItem = (NodeListItem *)FillList.GetNext(pItem);
05154 
05155                 //if (EnableBiasGain == FALSE)
05156                 //{
05157                 //  pItem = NULL;               // breakout as soon as possible !!!!
05158                 //}
05159             }
05160 
05161             FillList.DeleteAll();
05162         }
05163         
05164         switch (Mode)
05165         {   
05166             // I'm NOT sure if the NOFILL case is ever called for this tool (never fired off
05167             // the MessageBox during testing) - so for safety sake, we had best handle it ....
05168             case NOFILL:
05169                 EnableGadget(_R(IDC_MAPPING),       FALSE);
05170                 EnableGadget(_R(IDC_EFFECT),        FALSE);
05171                 EnableGadget(_R(IDC_BIASGAIN),      FALSE);
05172                 EnableGadget(_R(IDC_SELPOINT),      FALSE);
05173             break;
05174             
05175             case MANYFILLS:
05176             case FLATFILL:
05177                 // implicitly handles (FGMENU_FLATTRANSP)
05178                 // nothing else to enable ....
05179                 EnableGadget (_R(IDC_MAPPING), FALSE);
05180                 EnableGadget (_R(IDC_EFFECT), FALSE);
05181                 EnableGadget (_R(IDC_BIASGAIN), FALSE);
05182                 EnableGadget (_R(IDC_SELPOINT), FALSE);
05183                 EnableGadget (_R(IDC_SELCOLOUR), FALSE);
05184                 
05185                 // CGS:  don't ask me why this different to the transparency infobar, BUT for somereason,
05186                 // unless  I do the following test - the damn dialog is always closed!
05187                 // NOTE:  this is the code that closes the profile dialog when you have it open for a single
05188                 // fill; and then shift select a different fill ....
05189                 if (Mode == MANYFILLS)
05190                     CloseProfileDialog (m_BiasGainGadget);      // cause fill type cannot be profiled!
05191             break;
05192 
05193             case GRADFILL:
05194             case GRADREPEATFILL:
05195                 switch (CurrentGeometryIndex)
05196                 {
05197                     case FGMENU_LINEAR:
05198                     case FGMENU_CIRCULAR:
05199                     case FGMENU_RADIAL:
05200                     // the following is really fg_diamond ....
05201                     case FGMENU_SQUARE:
05202                         EnableGadget (_R(IDC_MAPPING), TRUE);
05203                         // if (2 colour)
05204                         EnableGadget (_R(IDC_BIASGAIN), EnableBiasGain);
05205                         EnableGadget (_R(IDC_SELPOINT), FALSE);
05206                         EnableGadget (_R(IDC_SELCOLOUR), FALSE);
05207                     break;
05208                     
05209                     case FGMENU_CONICAL:
05210                         EnableGadget (_R(IDC_MAPPING), FALSE);
05211                         //if (2 colour)
05212                         EnableGadget (_R(IDC_BIASGAIN), EnableBiasGain);
05213                         EnableGadget (_R(IDC_SELPOINT), FALSE);
05214                         EnableGadget (_R(IDC_SELCOLOUR), FALSE);
05215                     break;
05216                     
05217                     case FGMENU_THREECOL:
05218                     case FGMENU_FOURCOL:
05219                         EnableGadget (_R(IDC_MAPPING), TRUE);
05220                         EnableGadget (_R(IDC_EFFECT), FALSE);
05221                         EnableGadget (_R(IDC_BIASGAIN), FALSE);
05222                         EnableGadget (_R(IDC_SELPOINT), FALSE);
05223                         EnableGadget (_R(IDC_SELCOLOUR), FALSE);
05224                     break;
05225 
05226                 }
05227             break;
05228 
05229             case BITMAPFILL:
05230                 EnableGadget (_R(IDC_MAPPING), TRUE);
05231                 EnableGadget (_R(IDC_EFFECT), EnableAffect);//FALSE);
05232                 EnableGadget (_R(IDC_BITMAPEFFECT), TRUE);
05233                 //if (2 colour)
05234                 EnableGadget (_R(IDC_BIASGAIN), EnableBiasGain2);
05235 
05236                 if (GetGadgetWritable (_R(IDC_SELPOINT))) { EnableGadget (_R(IDC_SELPOINT), FALSE); }
05237                 else { EnableGadget (_R(IDC_SELPOINT), TRUE); }
05238                 
05239                 EnableGadget (_R(IDC_SELCOLOUR), FALSE);
05240             break;
05241 
05242             case FRACTALFILL:
05243             case NOISEFILL:
05244                 EnableGadget (_R(IDC_MAPPING), TRUE);
05245                 //if (2 colour)
05246                 EnableGadget (_R(IDC_BIASGAIN), TRUE);
05247 
05248                 if (GetGadgetWritable (_R(IDC_SELPOINT))) { EnableGadget (_R(IDC_SELPOINT), FALSE); }
05249                 else { EnableGadget (_R(IDC_SELPOINT), TRUE); }
05250                 
05251                 if (GetGadgetWritable (_R(IDC_SELCOLOUR))) { EnableGadget (_R(IDC_SELCOLOUR), FALSE); }
05252                 else
05253                 {
05254                     EnableGadget (_R(IDC_SELCOLOUR), TRUE);     // for selection bug !!!!
05255 
05256                     EnableGadget (_R(IDC_SELCOLOUR), TRUE);
05257                 }
05258             break;
05259 
05260             default:
05261             break;
05262         }
05263 
05264         if ((Mode != BITMAPFILL) && (Mode != NOFILL) && (Mode != MANYFILLS) && (Mode != FLATFILL)
05265             && (CurrentGeometryIndex != FGMENU_THREECOL) && (CurrentGeometryIndex != FGMENU_FOURCOL))
05266         {
05267             EnableGadget (_R(IDC_EFFECT), TRUE);
05268         }
05269     }
05270 }           
05271 
05272 /********************************************************************************************
05273 
05274 >   void GradInfoBarOp::ChangeFillType()
05275 
05276     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
05277     Created:    3/8/94
05278     Purpose:    Called when a new fill type is selected from the menu.
05279     Notes:      NeedsForceToSimpleMapping added for new fill types (Gerry 22/8/96)
05280 
05281 ********************************************************************************************/
05282 
05283 void GradInfoBarOp::ChangeFillType()
05284 {
05285     // Get the current fill type, and pass a new fill of that type into
05286     // the attribute manager, as a mutator.
05287     AttrFillGeometry* Mutator = MakeFillMutator();
05288 
05289     if (Mutator == NULL)
05290     {
05291         InformError();
05292         return;
05293     }
05294 
05295     // If the mutator requires a simple mapping but the current fill doesn't
05296     // then we need to set ForceToSimple to TRUE
05297     // Need to check this before we select the attribute
05298 
05299     //BOOL ForceToSimple = Mutator->NeedsForceToSimpleMapping() && AllowForceToSimpleMapping;
05300 
05301     // This call deletes the Mutator so I'll set the pointer to NULL
05302     AttributeManager::AttributeSelected(NULL, Mutator);     // cause this gives us our undoable !!!!
05303     Mutator = NULL;
05304 
05305     //if (ForceToSimple)
05306     //{
05307 //      CurrentMappingIndex = FMMENU_SIMPLE;
05308 //      ChangeFillMapping ();                   // we push two bits of undo here, but this is
05309                                                 // unavoidable at present ....
05310     //}
05311 }
05312 
05313 /********************************************************************************************
05314 
05315 >   void GradInfoBarOp::ChangeFillMapping()
05316 
05317     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
05318     Created:    3/11/94
05319     Purpose:    Called when a new fill mapping or tesselation is selected from the menu.
05320 
05321 ********************************************************************************************/
05322 
05323 void GradInfoBarOp::ChangeFillMapping()
05324 {
05325     if (Mode != BITMAPFILL && 
05326         Mode != FRACTALFILL && 
05327         Mode != GRADREPEATFILL &&
05328 // Mark Howitt, 6/10/97. Enable Gradual fill repeating/simple switching.
05329 #ifdef NEW_FEATURES
05330         Mode != GRADFILL &&         // also include gradual fills
05331 #endif
05332         Mode != NOISEFILL)
05333     {
05334         return;
05335     }
05336 
05337     INT32 Tesselation;
05338 
05339     switch (CurrentMappingIndex)
05340     {
05341         case (FTMENU_SIMPLE):
05342             Tesselation = 1;
05343             break;
05344     
05345         case (FTMENU_REPEAT):
05346 //Mark Howitt, 8/10/97. Check to see if gradfill is repeating and then set repeat value to 4 to show it`s special
05347 #ifdef NEW_FEATURES
05348             if(Mode==GRADFILL)
05349             {
05350                 Tesselation = 4;
05351             }
05352             else
05353 #endif
05354             {
05355                 Tesselation = 2;
05356             }
05357             break;
05358 
05359         case (FTMENU_REPEATINV):
05360             Tesselation = 3;
05361             break;
05362 
05363         default:
05364             Tesselation = 1;
05365             break;
05366     }
05367 
05368 /*
05369     AttrBitmapTessChange* TessChange = new AttrBitmapTessChange;
05370     if (TessChange == NULL)
05371     {
05372         InformError();
05373         return;
05374     }
05375 
05376     TessChange->SetTesselation(Tesselation);
05377 
05378     AttributeManager::AttributeSelected(NULL, TessChange);
05379 */
05380 
05381     AttrFillMappingLinear* NewMapping = new AttrFillMappingLinear;
05382     if (NewMapping == NULL)
05383     {
05384         InformError();
05385         return;
05386     }
05387 
05388     NewMapping->SetRepeat(Tesselation);
05389     AttributeManager::AttributeSelected(NewMapping);
05390 }
05391 
05392 /********************************************************************************************
05393 
05394 >   void GradInfoBarOp::ChangeFillEffect()
05395 
05396     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
05397     Created:    24/8/94
05398     Purpose:    Called when a new fill effect is selected from the menu.
05399 
05400 ********************************************************************************************/
05401 
05402 void GradInfoBarOp::ChangeFillEffect()
05403 {
05404     AttrFillEffect* FillEffect = NULL;
05405 
05406     switch (CurrentEffectIndex)
05407     {
05408         case (FEMENU_FADE):
05409             FillEffect = new AttrFillEffectFade;
05410             break;
05411     
05412         case (FEMENU_RAINBOW):
05413             FillEffect = new AttrFillEffectRainbow;
05414             break;
05415 
05416         case (FEMENU_ALTRAINBOW):
05417             FillEffect = new AttrFillEffectAltRainbow;
05418             break;
05419 
05420         default:
05421             FillEffect = new AttrFillEffectFade;
05422             break;
05423     }
05424 
05425     if (FillEffect == NULL)
05426     {
05427         InformError();
05428         return;
05429     }
05430 
05431     AttributeManager::AttributeSelected(FillEffect);
05432 }
05433 
05434 /********************************************************************************************
05435 
05436 >   void GradInfoBarOp::ChangeBitmapName()
05437 
05438     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
05439     Created:    14/12/94
05440     Purpose:    Called when a new bitmap is selected from the menu.
05441 
05442 ********************************************************************************************/
05443 
05444 void GradInfoBarOp::ChangeBitmapName()
05445 {
05446     AttrValueChange* NewBitmap = new AttrBitmapChange;
05447     if (NewBitmap == NULL)
05448     {
05449         InformError();
05450         return;
05451     }
05452 
05453     Document* pDoc = Document::GetSelected();
05454 
05455     // Get the bitmap list
05456     BitmapList* Bitmaps = NULL;
05457     if (pDoc) Bitmaps = pDoc->GetBitmapList();
05458 
05459     if (Bitmaps == NULL)
05460         return;
05461 
05462     INT32 BmpIndex = -1;
05463     ListItem* pBmp = Bitmaps->GetHead();
05464 
05465     while (pBmp != NULL)
05466     {
05467         if (!((KernelBitmap*)pBmp)->HasBeenDeleted())
05468             BmpIndex++;
05469 
05470         if (BmpIndex == CurrentEffectIndex)
05471             break;
05472 
05473         pBmp = Bitmaps->GetNext(pBmp);
05474     }
05475 
05476     ((AttrBitmapChange*)NewBitmap)->AttachBitmap((KernelBitmap*)pBmp);
05477     AttributeManager::AttributeSelected(NULL, NewBitmap);
05478 }
05479 
05480 
05481 /********************************************************************************************
05482 
05483 >   void GradInfoBarOp::ChangeDPI()
05484 
05485     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
05486     Created:    3/11/94
05487     Purpose:    Called when the dpi of a bitmap is changed by the user.
05488 
05489 ********************************************************************************************/
05490 
05491 void GradInfoBarOp::ChangeDPI()
05492 {
05493     BOOL Valid;
05494     String_256 Str = GetStringGadgetValue(_R(IDC_SELPOINT), &Valid);
05495 
05496     if (Valid)
05497     {
05498         TRACEUSER( "Will", _T("String = %s\n"),(TCHAR*)Str);
05499 
05500         INT32 Length = Str.Length();
05501         TCHAR* StrText = (TCHAR*)Str;
05502 
05503         INT32 FirstNum = -1;
05504         INT32 Count = 0;
05505 
05506         for (INT32 i = 0; i < Length; ++i)
05507         {
05508             TCHAR chr = StrText[i];
05509             if (FirstNum == -1 && StringBase::IsNumeric(chr))
05510                 FirstNum = i;
05511 
05512             if (FirstNum != -1)
05513             {
05514                 if (StringBase::IsNumeric(chr))
05515                     Count++;
05516                 else
05517                     break;
05518             }
05519         }
05520 
05521         String_256 DpiStr;
05522         INT32 Dpi;
05523 
05524         if (FirstNum != -1 && Count > 0)
05525         {
05526             Str.Mid(&DpiStr, FirstNum, Count);
05527             Convert::StringToLong(DpiStr, &Dpi);
05528             TRACEUSER( "Will", _T("Dpi = %d\n"),Dpi);
05529 
05530             if (Dpi == 0)
05531                 Dpi = 1;
05532 
05533             AttrValueChange* NewDpi = new AttrBitmapDpiChange;
05534             if (NewDpi == NULL)
05535             {
05536                 InformError();
05537                 return;
05538             }
05539 
05540             ((AttrBitmapDpiChange*)NewDpi)->SetDPI(Dpi);
05541 
05542             AttributeManager::AttributeSelected(NULL, NewDpi);
05543         }
05544         else
05545         {
05546             TRACEUSER( "Will", _T("That was rubbish\n"));
05547             ShowCommonBitmapDpi();
05548         }
05549     }
05550     else
05551         TRACEUSER( "Will", _T("String was invalid\n"));
05552 }
05553 
05554 /********************************************************************************************
05555 
05556 >   void GradInfoBarOp::ChangeFractalGrain()
05557 
05558     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
05559     Created:    11/11/94
05560     Purpose:    Called when the Graininess of a fractal is changed by the user.
05561 
05562 ********************************************************************************************/
05563 
05564 void GradInfoBarOp::ChangeFractalGrain()
05565 {
05566     BOOL Valid;
05567     String_256 Str = GetStringGadgetValue(_R(IDC_SELCOLOUR), &Valid);
05568 
05569     if (Valid)
05570     {
05571         TRACEUSER( "Will", _T("String = %s\n"),(TCHAR*)Str);
05572 
05573         double Grain = 1.0;
05574         UnitType Units;
05575 
05576         if (Convert::StringToComponents(Str, &Grain, &Units))
05577         {
05578             TRACEUSER( "Will", _T("Graininess = %f\n"),Grain);
05579 
05580             if (Grain < 0.1)
05581                 Grain = 0.1;
05582 
05583             if (Grain > 16384)
05584                 Grain = 16384;
05585 
05586             AttrValueChange* NewGrain = new AttrFractalGrainChange;
05587             if (NewGrain == NULL)
05588             {
05589                 InformError();
05590                 return;
05591             }
05592 
05593             ((FractalFillAttribute*)NewGrain->GetAttributeValue())->Graininess = FIXED16(Grain);
05594 
05595             AttributeManager::AttributeSelected(NULL, NewGrain);
05596         }
05597         else
05598         {
05599             TRACEUSER( "Will", _T("That was rubbish\n"));
05600             ShowCommonFractalGrain();
05601         }
05602     }
05603 }
05604 
05605 /********************************************************************************************
05606 
05607 >   void GradInfoBarOp::ChangeNoiseScale()
05608 
05609     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
05610     Created:    20/01/95
05611     Purpose:    Called when the Scale of a noise fill is changed by the user.
05612 
05613 ********************************************************************************************/
05614 
05615 void GradInfoBarOp::ChangeNoiseScale()
05616 {
05617     BOOL Valid;
05618     String_256 Str = GetStringGadgetValue(_R(IDC_SELCOLOUR), &Valid);
05619 
05620     if (Valid)
05621     {
05622         TRACEUSER( "Will", _T("String = %s\n"),(TCHAR*)Str);
05623 
05624         double Scale = 1.0;
05625         UnitType Units;
05626 
05627         if (Convert::StringToComponents(Str, &Scale, &Units))
05628         {
05629             TRACEUSER( "Mike", _T("Noise scale = %f\n"),Scale);
05630 
05631             if (Scale < 1)
05632                 Scale = 1;
05633 
05634             if (Scale > 100)
05635                 Scale = 100;
05636 
05637             AttrValueChange* NewScale = new AttrNoiseScaleChange;
05638             if (NewScale == NULL)
05639             {
05640                 InformError();
05641                 return;
05642             }
05643 
05644             FIXED16 Grain = FIXED16(Scale);
05645             ((NoiseFillAttribute*)NewScale->GetAttributeValue())->SetGraininess(Grain);
05646 
05647             AttributeManager::AttributeSelected(NULL, NewScale);
05648         }
05649         else
05650         {
05651             TRACEUSER( "Will", _T("That was rubbish\n"));
05652             ShowCommonNoiseScale();
05653         }
05654     }
05655 }
05656 
05657 /********************************************************************************************
05658 
05659 >   AttrFillGeometry* GradInfoBarOp::MakeFillMutator()
05660 
05661     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
05662     Created:    10/8/94
05663     Purpose:    Make a fill that will be used to Mutate another fill, changing it's type 
05664                 while retaining it's existing points and colours.
05665                 The fill type returned depends on the fill type menu state.
05666 
05667 ********************************************************************************************/
05668 
05669 AttrFillGeometry* GradInfoBarOp::MakeFillMutator()
05670 {
05671     AttrFillGeometry* Fill = NULL;
05672     KernelBitmap* Default;
05673 
05674     switch (CurrentGeometryIndex)
05675     {
05676         case (FGMENU_FLAT):
05677             Fill = new AttrFlatColourFill;
05678             break;
05679 
05680         case (FGMENU_LINEAR):
05681             Fill = new AttrLinearColourFill;
05682             break;
05683     
05684         case (FGMENU_CIRCULAR):
05685             Fill = new AttrRadialColourFill;
05686             if (Fill != NULL)
05687                 ((AttrRadialFill*)Fill)->MakeCircular();
05688             break;
05689     
05690         case (FGMENU_RADIAL):
05691             Fill = new AttrRadialColourFill;
05692             if (Fill != NULL)
05693                 ((AttrRadialFill*)Fill)->MakeElliptical();
05694             break;
05695     
05696         case (FGMENU_CONICAL):
05697             Fill = new AttrConicalColourFill;
05698             break;
05699     
05700         case (FGMENU_SQUARE):
05701             Fill = new AttrSquareColourFill;
05702             break;
05703     
05704         case (FGMENU_THREECOL):
05705             Fill = new AttrThreeColColourFill;
05706             CloseProfileDialog (m_BiasGainGadget);      // cause fill type cannot be profiled!
05707             break;
05708     
05709         case (FGMENU_FOURCOL):
05710             Fill = new AttrFourColColourFill;
05711             CloseProfileDialog (m_BiasGainGadget);      // cause fill type cannot be profiled!
05712             break;
05713     
05714         case (FGMENU_BITMAP):
05715             Fill = new AttrBitmapColourFill;
05716             CloseProfileDialog (m_BiasGainGadget);      // cause fill type cannot be profiled!
05717 
05718             Default = KernelBitmap::MakeKernelBitmap();
05719             if (Default == NULL)
05720             {
05721                 delete Fill;
05722                 return NULL;
05723             }
05724 
05725             Fill->AttachBitmap(Default);
05726             break;
05727 
05728         case (FGMENU_FRACTAL):
05729             Fill = new AttrFractalColourFill;
05730             break;
05731 
05732         case (FGMENU_NOISE):
05733             Fill = new AttrNoiseColourFill;
05734             break;
05735 
05736         default:
05737             // Er .. Dunno what kind of fill this is ?
05738             Fill = new AttrFlatColourFill;
05739             break;
05740     }
05741 
05742     return Fill;
05743 }
05744 
05745 /********************************************************************************************
05746 
05747 >   AttrFillGeometry* GradInfoBarOp::GetCurrentGeometry()
05748 
05749     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
05750     Created:    10/8/94
05751     Purpose:    Gets the current Fill Geometry from the Attribute manager.
05752 
05753 ********************************************************************************************/
05754 
05755 AttrFillGeometry* GradInfoBarOp::GetCurrentGeometry()
05756 {
05757     CCRuntimeClass* CurrentAttribGroup = 
05758         Tool::GetCurrent()->Parent->m_ToolInfo.CurrentAttributeGroup;
05759 
05760     Document* CurrentDoc = Document::GetSelected();
05761 
05762     if (CurrentDoc == NULL)
05763         return NULL; // We are not going to be able to do anything if there is no document
05764 
05765     return (AttrFillGeometry*)CurrentDoc->GetAttributeMgr()
05766                                 .GetCurrentAttribute(CurrentAttribGroup, 
05767                                             CC_RUNTIME_CLASS(AttrFillGeometry));
05768 }
05769 
05770 
05771 /********************************************************************************************
05772 
05773 >   AttrFillMapping* GradInfoBarOp::GetCurrentMapping()
05774 
05775     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
05776     Created:    10/8/94
05777     Purpose:    Gets the current Fill Geometry from the Attribute manager.
05778 
05779 ********************************************************************************************/
05780 
05781 AttrFillMapping* GradInfoBarOp::GetCurrentMapping()
05782 {
05783     CCRuntimeClass* CurrentAttribGroup = 
05784         Tool::GetCurrent()->Parent->m_ToolInfo.CurrentAttributeGroup;
05785 
05786     Document* CurrentDoc = Document::GetSelected();
05787 
05788     if (CurrentDoc == NULL)
05789         return NULL; // We are not going to be able to do anything if there is no document
05790 
05791     return (AttrFillMapping*)CurrentDoc->GetAttributeMgr()
05792                                 .GetCurrentAttribute(CurrentAttribGroup, 
05793                                             CC_RUNTIME_CLASS(AttrFillMapping));
05794 }
05795 
05796 
05797 
05798 
05799 
05800 
05801 
05802 
05803 
05804 
05805 
05806 
05807 
05808 
05809 
05810 
05811 
05812 
05815 
05816 //          Implementation of class TranspInfoBarOp (transparency tools infobar)
05817 
05820 
05821 
05822 
05823 /********************************************************************************************
05824 
05825 >   struct TGMItem 
05826 
05827     Author:     Martin_Bell (Xara Group Ltd) <camelotdev@xara.com>
05828     Created:    23/06/97
05829     Purpose:    Associate the TransparencyGeometry enum with the resource id of the text that
05830                 gets displayed on the menu.
05831     SeeAlso:    FGMItem, TransparencyGeometry enum
05832 
05833 ********************************************************************************************/
05834 
05835 struct TGMItem
05836 {
05837     TransparencyGeometry Geometry;
05838     unsigned StringID;
05839 };
05840 
05841 /********************************************************************************************
05842 
05843 >   const TGMItem TransparencyGeometryMenu[] 
05844 
05845     Author:     Martin_Bell (Xara Group Ltd) <camelotdev@xara.com>
05846     Created:    23/06/97
05847     Purpose:    Array of 'TGMItem's that make up the geometry menu. We need to keep track of
05848                 this because list combo boxes can only return the position of the selected
05849                 item, not what itd actually is. All this fuctionality should be in the gadgets
05850                 not here.
05851     SeeAlso:    TransparencyGeometry enum, FillGeometryMenu
05852 
05853 ********************************************************************************************/
05854 
05855 const TGMItem TransparencyGeometryMenu[] =
05856 {
05857     { FGMENU_NOTRANSP,          _R(IDS_FILLTOOL_NOTRANSP) },
05858     { FGMENU_FLATTRANSP,        _R(IDS_FILLTOOL_FLATTRANSP) },
05859     { FGMENU_LINEARTRANSP,      _R(IDS_FILLTOOL_LINEAR) },
05860     { FGMENU_CIRCULARTRANSP,    _R(IDS_FILLTOOL_CIRCULAR) },
05861     { FGMENU_RADIALTRANSP,      _R(IDS_FILLTOOL_ELLIPTICAL) },
05862 #ifndef WEBSTER
05863     { FGMENU_CONICALTRANSP,     _R(IDS_FILLTOOL_CONICAL) },
05864     { FGMENU_SQUARETRANSP,      _R(IDS_FILLTOOL_SQUARE) },
05865     { FGMENU_THREECOLTRANSP,    _R(IDS_FILLTOOL_THREECOLTRANS) },
05866     { FGMENU_FOURCOLTRANSP,     _R(IDS_FILLTOOL_FOURCOLTRANS) },
05867 #endif //WEBSTER
05868     { FGMENU_BITMAPTRANSP,      _R(IDS_FILLTOOL_TEXTURE) },
05869     { FGMENU_FRACTALTRANSP,     _R(IDS_FILLTOOL_FRACTAL) },
05870 #ifndef WEBSTER
05871     { FGMENU_NOISETRANSP,       _R(IDS_FILLTOOL_NOISE) }
05872 #endif //WEBSTER
05873 };
05874 
05875 /********************************************************************************************
05876 
05877 >   const INT32 TransparencyGeometryMenuCount 
05878 
05879     Author:     Martin_Bell (Xara Group Ltd) <camelotdev@xara.com>
05880     Created:    23/06/97
05881     Purpose:    Number of items on the TransparencyGeometryMenu menu.
05882     SeeAlso:    TransparencyGeometryMenu
05883 
05884 ********************************************************************************************/
05885 
05886 const INT32 TransparencyGeometryMenuCount = sizeof(TransparencyGeometryMenu) / sizeof(TransparencyGeometryMenu[0]);
05887 
05888 /********************************************************************************************
05889 
05890 >   MsgResult TranspInfoBarOp::Message(Msg* Message) 
05891 
05892     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
05893     Created:    3/8/94
05894     Inputs:     Message: The message to handle
05895     Outputs:    -
05896     Returns:    -
05897     Purpose:    Transpfill info bar dialog message handler
05898     Errors:     -
05899     SeeAlso:    -
05900 
05901 ********************************************************************************************/
05902 
05903 MsgResult TranspInfoBarOp::Message(Msg* Message) 
05904 {
05905     if (!TranspTool::IsCurrentTool() || !IsVisible())
05906         return (InformationBarOp::Message(Message));
05907 
05908     if (IS_OUR_DIALOG_MSG(Message))
05909     {
05910         DialogMsg* Msg = (DialogMsg*)Message;
05911 
05912         // Check if the message is a CANCEL
05913         if (Msg->DlgMsg == DIM_CANCEL)
05914         {
05915             Close(); // Close the dialog 
05916         }
05917         else if (Msg->DlgMsg == DIM_CREATE)
05918         {
05919             // Initialise the controls 
05920             SliderDragged = FALSE;
05921             InitControls();
05922         }
05923         else
05924         {
05925             if (Msg->GadgetID == _R(IDC_GEOMETRY))
05926             {
05927                 switch (Msg->DlgMsg)
05928                 {
05929                     case DIM_SELECTION_CHANGED :
05930                     {
05931                         ShowCommonType (FALSE);     // specifying false means that this
05932                                                     // gets (but does not show) CurrentGeometryIndex
05933                         
05934                         // Someone selected a new Fill Geometry
05935                         INT32 Index;
05936                         GetValueIndex(_R(IDC_GEOMETRY),&Index);
05937 
05938                         // pointless doing all that work if the user has selected
05939                         // the currently applied transparency geometry ....
05940 
05941                         if (CurrentGeometryIndex != Index)
05942                         {
05943                             // Change the Fill Geometry Here
05944                             CurrentGeometryIndex = TransparencyGeometryMenu[Index].Geometry;
05945                             ChangeFillType();
05946                             EnableControls();
05947                         }
05948                     }
05949                     break;
05950 
05951                     default:
05952                         break;
05953                 }
05954             }
05955 
05956             else if (Msg->GadgetID == _R(IDC_TRANSPTYPE))
05957             {
05958                 switch (Msg->DlgMsg)
05959                 {
05960                     case DIM_SELECTION_CHANGED:
05961                     {
05962                         ShowCommonTranspType (FALSE);       // specifying false means that this
05963                                                             // gets (but does not show) CurrentTransTypeIndex
05964                         
05965                         // Someone selected a new Fill Mapping
05966                         INT32 Index;  
05967                         GetValueIndex (_R(IDC_TRANSPTYPE), &Index);
05968 
05969                         if (CurrentTransTypeIndex != Index)
05970                         {
05971                             if (Index >= 0 && Index < FTMENU_MAX)
05972                             {
05973                                 // Change the Fill Mapping Here
05974                                 CurrentTransTypeIndex = Index;
05975                                 EnableControls ();
05976                                 ChangeTranspType ();
05977                             }
05978                             else
05979                             {
05980                                 ShowInfo();
05981                             }
05982                         }
05983                     }
05984                     break;
05985 
05986                     default:
05987                         break;
05988                 }
05989             }
05990 
05991             else if (Msg->GadgetID == _R(IDC_MAPPING))
05992             {
05993                 switch (Msg->DlgMsg)
05994                 {
05995                     case DIM_SELECTION_CHANGED:
05996                     {
05997                         ShowCommonMapping (FALSE);  // specifying false means that this
05998                                                     // gets (but does not show) CurrentMappingIndex
05999                         
06000                         // Someone selected a new Fill Mapping
06001                         INT32 Index;  
06002                         GetValueIndex(_R(IDC_MAPPING),&Index);
06003 
06004                         if (CurrentMappingIndex != Index)
06005                         {
06006                             // Change the Fill Mapping Here
06007                             CurrentMappingIndex = Index;
06008                             ChangeFillMapping();
06009                         }
06010                     }
06011                     break;
06012 
06013                     default:
06014                         break;
06015                 }
06016             }
06017 
06018             else if (Msg->GadgetID == _R(IDC_BITMAPEFFECT))
06019             {
06020                 switch (Msg->DlgMsg)
06021                 {
06022                     case DIM_SELECTION_CHANGED:
06023                     {
06024                         // Someone selected a new bitmap Fill Effect
06025                         INT32 Index = m_oBitmapDropDown.GetSelected();
06026 
06027                         //if (CurrentBitmapIndex != Index)
06028                         //{
06029                             // Change the bitmap Fill Effect Here
06030                             INT32 OldBitmapIndex = CurrentBitmapIndex;
06031                         
06032                             CurrentBitmapIndex = Index;
06033                             
06034                             if (!ChangeBitmapName ())
06035                             {
06036                                 CurrentBitmapIndex = OldBitmapIndex;
06037                                 ShowInfo();
06038                             }
06039                         //}
06040                     }
06041                     break;                                                 
06042 
06043                     default:
06044                         break;
06045                 }
06046             }
06047 
06048             else if (Msg->GadgetID == _R(IDC_BIASGAIN))
06049             {
06050                 switch (Msg->DlgMsg)
06051                 {
06052                     case DIM_LFT_BN_CLICKED:
06053                         HandleProfileButtonClick (m_BiasGainGadget, _R(IDC_BIASGAIN));
06054                         break;
06055 
06056                     default:
06057                         ProfileSelectionChange( Msg, Msg->GadgetID );
06058                         break;
06059                 }
06060             }
06061 
06062             else if (Msg->GadgetID == _R(IDC_SELPOINT))
06063             {
06064                 switch (Msg->DlgMsg)
06065                 {
06066                     case DIM_SELECTION_CHANGED:
06067                     {
06068                         if (AttrFillGeometry::SelectionCount == 0)
06069                         {
06070                             if (Mode == BITMAPFILL || 
06071                                 Mode == FRACTALFILL ||
06072                                 Mode == NOISEFILL
06073                                 )
06074                             {
06075                                 ChangeDPI();
06076                             }
06077                         }
06078                     }
06079                     break;                                                 
06080 
06081                     default:
06082                         break;
06083                 }
06084             }
06085 
06086             else if (Msg->GadgetID == _R(IDC_SELCOLOUR))
06087             {
06088                 switch (Msg->DlgMsg)
06089                 {
06090                     case DIM_SELECTION_CHANGED:
06091                     {
06092                         //if (AttrFillGeometry::SelectionCount == 0)
06093                         //{
06094                         //  if (Mode == BITMAPFILL || 
06095                         //      Mode == FRACTALFILL || 
06096                         //      Mode == NOISEFILL ) 
06097                         //  {
06098                             //  ChangeTransparencyValue();
06099                         //  }
06100                         //}
06101 
06102                         if (Mode==FRACTALFILL && AttrFillGeometry::SelectionCount==0)
06103                         {
06104                             ChangeFractalGrain (TRUE);
06105                         }
06106                         else if (Mode==NOISEFILL && AttrFillGeometry::SelectionCount==0)
06107                         {
06108                             ChangeNoiseScale (TRUE);
06109                         }
06110                         else
06111                         {
06112                             ChangeTransparencyValue ();
06113                         }
06114                     }
06115                     break;
06116 
06117                     default:
06118                         break;
06119                 }
06120             }
06121 
06122             else if (Msg->GadgetID == _R(IDC_TRANSPSLIDE))
06123             {
06124                 switch (Msg->DlgMsg)
06125                 {
06126                     case DIM_SLIDER_POS_CHANGING:
06127                     {
06128                         GetApplication ()->LockOutControlHelp ();
06129                         // Find the current scrollers position
06130                         TCHAR Str[32];
06131                         BOOL Valid;
06132                         INT32 Result = GetLongGadgetValue(_R(IDC_TRANSPSLIDE), 0, SliderMax, 0, &Valid);
06133 
06134                         if (LastSliderPos == Result)
06135                             break;
06136 
06137                         double Grain = 1.0;
06138                         BOOL flag = TRUE;
06139 
06140                         if (AttrFillGeometry::SelectionCount == 0)
06141                         {
06142                             if (Mode == FRACTALFILL)
06143                             {
06144                                 Grain = GetDoubleGrain(Result); 
06145                                 flag = FALSE;
06146                             }
06147                             if (Mode == NOISEFILL)
06148                             {
06149                                 Grain = GetDoubleScale(Result);
06150                                 flag = FALSE;
06151                             }
06152 
06153                             if (!flag)
06154                             {
06155                                 if (Mode == FRACTALFILL)
06156                                 {
06157                                     camSnprintf(Str, 31, _T("%.1f"), Grain);
06158                                 }
06159                             }
06160                         }
06161 
06162                         if (flag)
06163                         {
06164                             double Transp = (double) Result;
06165                             //Result = ((SliderMax - Result) * 100) / SliderMax;
06166 
06167                             // Build the Percentage string and set it
06168                             //String_32 jcf(_R(IDS_PERCENT_FORMAT));
06169                             //wsprintf(Str, jcf, Result);
06170 
06171                             DisplayTransparencyPercentString ((double) Transp); // and display it
06172 
06173                             if (GetApplication()->FindSelection()->Count() <= 64)
06174                             {
06175                                 // Don't let transp get to Zero, or the 'Repeat'
06176                                 // op will get confused
06177                                 // if (Transp == 0) Transp = 1;
06178 
06179                                 AttributeManager::SendMessages = FALSE;
06180                                 SetTranspValue(static_cast<UINT32>(Transp), TRUE, !SliderDragged);
06181                             }
06182                         }
06183                         else
06184                         {
06185                             if (Mode == FRACTALFILL)
06186                             {
06187                                 String_32 PercentStr(Str);
06188                                 SetStringGadgetValue(_R(IDC_SELCOLOUR), PercentStr);
06189                             }
06190                             else    // MUST be NOISEFILL
06191                             {
06192                                 String_64 Str;
06193 
06194                                 Convert::DoubleToString( Grain, &Str, 1 );
06195         
06196                                 Str.MakePercent ((TCHAR*) Str);
06197 
06198                                 String_64 PercentStr(Str);
06199                                 SetGadgetString(_R(IDC_SELCOLOUR), &PercentStr);
06200                             }
06201                         }
06202 
06203                         LastSliderPos = Result;
06204 
06205                         SliderDragged = TRUE;
06206                     }
06207                     break;
06208 
06209                     case DIM_SLIDER_POS_IDLE:
06210                     {
06211                         // Slider control generates an "IDLE" event after processing
06212                         // a run of WM_MOUSEWHEEL messages... Oh dear...
06213                         //if (SliderDragged)
06214                         {
06215                             GetApplication ()->LockOutControlHelp ();
06216                             // Find the current scrollers position
06217                             TCHAR Str[32];
06218                             BOOL Valid;
06219                             INT32 Result = GetLongGadgetValue(_R(IDC_TRANSPSLIDE), 0, SliderMax, 0, &Valid);
06220                             // if (LastSliderPos == Result)
06221                             //  break;
06222 
06223                             LastSliderPos = Result;
06224                         
06225                             double val = 1.0;
06226                             BOOL flag = TRUE;
06227 
06228                             if (AttrFillGeometry::SelectionCount == 0)
06229                             {
06230                                 if (Mode == FRACTALFILL)
06231                                 {
06232                                     val = GetDoubleGrain(Result);   
06233                                     flag = FALSE;
06234                                 }
06235                                 if (Mode == NOISEFILL)
06236                                 {
06237                                     val = GetDoubleScale(Result);
06238                                     flag = FALSE;
06239                                 }
06240 
06241                                 if (!flag)
06242                                 {
06243                                     if (Mode == FRACTALFILL)
06244                                     {
06245                                         camSnprintf(Str, 31, _T("%.1f"), val);
06246                                     }
06247                                 }
06248                             }
06249                             
06250                             if (flag)
06251                             {
06252                                 double Transp = (double) Result;
06253                                 //Result = ((SliderMax - Result) * 100) / SliderMax;
06254 
06255                                 // Build the Percentage string and set it
06256                                 //String_32 jcf(_R(IDS_PERCENT_FORMAT));
06257                                 //wsprintf(Str, jcf, Result);
06258 
06259                                 DisplayTransparencyPercentString ((double) Transp); // and display it
06260 
06261                                 if (GetApplication()->FindSelection()->Count() <= 64)
06262                                 {
06263                                     // Don't let transp get to Zero, or the 'Repeat'
06264                                     // op will get confused
06265                                     // if (Transp == 0) Transp = 1;
06266 
06267                                     AttributeManager::SendMessages = FALSE;
06268                                     // SetTranspValue(static_cast<UINT32>(Transp), TRUE);
06269                                     // Treat Idle events as SET events because of the way the damn Slider control handles mouse wheel events...
06270                                     SetTranspValue(static_cast<UINT32>(Transp));
06271                                     SliderDragged = FALSE;
06272                                 }
06273                             }
06274                             else
06275                             {
06276                                 if (Mode == FRACTALFILL)
06277                                 {
06278                                     String_32 PercentStr(Str);
06279                                     SetStringGadgetValue(_R(IDC_SELCOLOUR), PercentStr);
06280                                 }
06281                                 else    // MUST be NOISEFILL
06282                                 {
06283                                     String_64 Str;
06284 
06285                                     Convert::DoubleToString( val, &Str, 1 );
06286         
06287                                     Str.MakePercent ((TCHAR*) Str);
06288 
06289                                     String_64 PercentStr(Str);
06290                                     SetGadgetString(_R(IDC_SELCOLOUR), &PercentStr);
06291                                 }
06292                             }
06293                         }
06294                     }
06295                     break;
06296 
06297                     case DIM_SLIDER_POS_SET:
06298                     {
06299                         // Find the current scrollers position
06300                         BOOL Valid;
06301                         INT32 Result = GetLongGadgetValue(_R(IDC_TRANSPSLIDE), 0, SliderMax, 0, &Valid);
06302                         LastSliderPos = Result;
06303 
06304                         Operation::SetQuickRender(FALSE);
06305 
06306                         // Tell the freehand tool about the new smoothness
06307                         if (Valid)
06308                         {
06309                             AttributeManager::SendMessages = TRUE;
06310 
06311                             if (Mode==FRACTALFILL && AttrFillGeometry::SelectionCount==0)
06312                                 ChangeFractalGrain();
06313                             else if (Mode==NOISEFILL && AttrFillGeometry::SelectionCount==0)
06314                                 ChangeNoiseScale();
06315                             else
06316                                 SetTranspValue(Result);
06317 
06318                             GetApplication ()->UnlockControlHelp ();
06319                         }
06320 
06321                         SliderDragged = FALSE;
06322                         break;
06323                     }
06324 
06325                     default:
06326                         break;
06327                 }
06328             }
06329     
06330         }
06331     }
06332 
06333     if (MESSAGE_IS_A(Message, SelChangingMsg) ||
06334         MESSAGE_IS_A(Message, CurrentAttrChangedMsg))
06335     {
06336         // The selection has changed in some way
06337 
06338         // Re-Count the number of selected fill control points
06339         AttrFillGeometry::SetSelectionCount(AttrFillGeometry::CountSelectionControlPoints());
06340 
06341         if (AttrFillGeometry::SelectionCount > 0)
06342         {
06343             TranspTool::EnableFillNudge();
06344         }
06345         else
06346         {
06347             TranspTool::DisableFillNudge();
06348         }
06349 
06350         HandleProfileSelChangingMsg (m_BiasGainGadget, _R(IDC_BIASGAIN));
06351 
06352         ShowInfo();
06353 /*
06354         SelChangingMsg* Msg = (SelChangingMsg*)Message;
06355         switch (Msg->State)
06356         {
06357             case SelChangingMsg::COLOURATTCHANGED:
06358                 // The colour of an attribute has changed
06359                 InitControls();
06360                 break;
06361 
06362             case SelChangingMsg::NONCOLOURATTCHANGED:
06363                 // The selection state or control points of an attribute have changed
06364                 InitControls();
06365                 break;
06366         }
06367 */
06368     }
06369     
06370     // Pass the message on
06371     return (InformationBarOp::Message(Message));
06372 }
06373 
06374 
06375 /********************************************************************************************
06376 
06377 >   void TranspInfoBarOp::ChangeProfile(CProfileBiasGain* Profile, CGadgetID GadgetID)
06378 
06379     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
06380     Created:    7/2/2000
06381     Purpose:    See InformationBarOp::ChangeProfile () for an explanation of this function.
06382     See Also:   InformationBarOp::ChangeProfile ()
06383 
06384 *********************************************************************************************/
06385 
06386 void TranspInfoBarOp::ChangeProfile(CProfileBiasGain* Profile, CGadgetID GadgetID)
06387 {
06388     OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_TRANSPFILLPROFILE);
06389     if (pOpDesc != NULL)
06390     {
06391         BOOL FireOp = TRUE;
06392 
06393         // we only want to generate one bit of undo information - so decided whether
06394         // we have to fire the above op, or whether we just 'pump' the values into
06395         // our nodes (thereby nolonger generating infinite undo information) ....
06396 
06397         Operation* pLastOp = NULL;
06398 
06399         if (Profile->GetGeneratesInfiniteUndo ())   // only do if they didn't select a preset profile
06400         {
06401             pLastOp = Document::GetSelected()->GetOpHistory().FindLastOp();
06402         }
06403 
06404         if (pLastOp)
06405         {
06406             if (pLastOp->GetRuntimeClass() == CC_RUNTIME_CLASS(OpChangeTranspFillProfile))
06407             {
06408                 FireOp = FALSE;
06409             }
06410         }
06411 
06412         if (FireOp == TRUE)
06413         {
06414             TranspFillProfileOpParam Param;
06415             Param.Profile = *Profile;
06416         
06417             pOpDesc->Invoke(&Param);
06418         }
06419         else
06420         {
06421             // we don't need/want any undo information - so just change the value ....
06422             
06423             //OpChangeFillProfile Op;
06424             ChangeTranspFillProfileAction Action;
06425             Action.ChangeTranspFillProfileWithNoUndo (/*&Op,*/ *Profile);
06426         }
06427         
06428         /*AFp BiasValue = Profile->GetBias();
06429         AFp GainValue = Profile->GetGain();
06430         
06431         TranspFillProfileOpParam Param;
06432         Param.Profile.SetBias(BiasValue);
06433         Param.Profile.SetGain(GainValue);
06434         
06435         pOpDesc->Invoke(&Param);*/
06436     }
06437 }
06438 
06439 
06440 
06441 /********************************************************************************************
06442 
06443 >   virtual CProfileBiasGain* GetProfileFromSelection(CGadgetID GadgetID, INT32* Index, BOOL* bAllSameType)
06444 
06445     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
06446     Created:    7/2/2000
06447     Inputs:     The GadgetID of the CBiasGainGadget that we are dealing with.
06448     Outputs:    bMany - returned as TRUE if we have MANY profiles selected.
06449                 bAllSameType - returned as TRUE if objects within selection are all of the
06450                 same type.
06451     returns     Ptr to common CProfileBiasGain, or NULL if there is NOT one.
06452     Purpose:    See InformationBarOp::GetProfileFromSelection () for a description of this
06453                 function.
06454 
06455 *********************************************************************************************/
06456 
06457 CProfileBiasGain* TranspInfoBarOp::GetProfileFromSelection(CGadgetID GadgetID, BOOL* bMany, BOOL* bAllSameType)
06458 {
06459     BOOL ok = (GadgetID == _R(IDC_BIASGAIN));
06460 
06461     ERROR2IF(ok==FALSE, FALSE, "Invalid gadgetID passed");
06462     
06463     UINT32 TotalNumberSelected = (GetApplication()->FindSelection()->Count ());
06464 
06465     // get the list of all the shadows
06466 //  List ShadowList;
06467 //  FillTools::BuildListOfSelectedAttrs(&ShadowList, CC_RUNTIME_CLASS(AttrTranspFillGeometry));
06468     List AttrList;
06469     ok = FillTools::GetSelectedAttrList(&AttrList, CC_RUNTIME_CLASS(AttrTranspFillGeometry), TRUE, TRUE);
06470     if (!ok)
06471         return NULL;
06472 
06473     AttrFillGeometry* pFirstNodeShadow = NULL;
06474     FillGeometryAttribute* pFirstFillGeoAttr = NULL;
06475 
06476     CProfileBiasGain* pFirstProfile = NULL;
06477 
06478 //  NodeListItem * pItem = (NodeListItem *)ShadowList.GetHead();
06479     NodeListItem * pItem = (NodeListItem *)AttrList.GetHead();
06480 
06481     while (pItem)
06482     {
06483         if (pFirstNodeShadow == NULL)
06484         {
06485             pFirstNodeShadow = (AttrFillGeometry*) pItem->pNode;
06486             pFirstFillGeoAttr = (FillGeometryAttribute*) pFirstNodeShadow->GetAttributeValue ();
06487 
06488             pFirstProfile = pFirstFillGeoAttr->GetProfilePtr ();
06489         }
06490         else
06491         {       
06492             CProfileBiasGain* pOtherProfile = NULL;
06493             
06494             pOtherProfile = ((FillGeometryAttribute*) ((AttrFillGeometry*)pItem->pNode)->GetAttributeValue ())->GetProfilePtr ();
06495 
06496             if (pOtherProfile)
06497             {
06498                 if (*pFirstProfile == *pOtherProfile)
06499                 {
06500                     // all ok
06501                 }
06502                 else
06503                 {
06504                     *bMany = TRUE;
06505                 }
06506             }
06507         }
06508 
06509 //      pItem = (NodeListItem *)ShadowList.GetNext(pItem);
06510         pItem = (NodeListItem *)AttrList.GetNext(pItem);
06511     }
06512 
06513 //  if (TotalNumberSelected != (UINT32) ShadowList.GetCount ())
06514     if (TotalNumberSelected != (UINT32) AttrList.GetCount ())
06515     {
06516         // totals differ - so the user MUST have selected someother type of node as well
06517         
06518         if ((pFirstProfile) && (*bMany == FALSE))
06519         {
06520             // scan each node in the list, and see if they have the attribute applied ....
06521 
06522             SelRange* range = GetApplication()->FindSelection();
06523 
06524             NodeRenderableInk* pNode = (NodeRenderableInk*) range->FindFirst();
06525             NodeAttribute* pAttr;
06526 
06527             while (pNode)
06528             {
06529 //              if (pNode->FindAppliedAttribute (CC_RUNTIME_CLASS (AttrTranspFillGeometry), &pAttr))
06530                 pAttr = pNode->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrTranspFillGeometry));
06531                 if (pAttr)
06532                 {
06533                     pNode = (NodeRenderableInk*) (range->FindNext(pNode));
06534                 }
06535                 else
06536                 {
06537                     // the node ain't got one
06538 
06539                     *bAllSameType = FALSE;
06540 //                  ShadowList.DeleteAll();
06541                     AttrList.DeleteAll();
06542                     return (NULL);
06543                 }
06544             }
06545         }
06546         else
06547         {   
06548             *bAllSameType = FALSE;
06549 //          ShadowList.DeleteAll();
06550             AttrList.DeleteAll();
06551             return (NULL);
06552         }
06553     }
06554     
06555     // I've assumed that m_BiasGainGadget.UseTranspFillProfile () has already been called ....
06556     // (which in this code it will have been).
06557     
06558     if (*bMany == TRUE)
06559     {
06560 //      ShadowList.DeleteAll();
06561         AttrList.DeleteAll();
06562         return (NULL);
06563     }
06564     else
06565     {
06566         // NOTE:  we can only be 'context' sensitive for a single fill within the
06567         // selection - so lets just choose the first one that we came accross ....
06568         
06569         if (pFirstNodeShadow)
06570         {
06571             m_BiasGainGadget.SetStartTransp (pFirstNodeShadow->GetStartTransp ());
06572             m_BiasGainGadget.SetEndTransp (pFirstNodeShadow->GetEndTransp ());
06573         }
06574 
06575 //      ShadowList.DeleteAll();
06576         AttrList.DeleteAll();
06577 
06578         return (pFirstProfile);
06579     }
06580 }
06581 
06582 /********************************************************************************************
06583 
06584 >   void TranspInfoBarOp::InitControls()
06585 
06586     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
06587     Created:    3/8/94
06588     Purpose:    Inits all the controls in the info bar.
06589                 Called immediately after the bar is created when the Transpfill tool
06590                 becomes the current tool.
06591     SeeAlso:    -
06592     Note:       WEBSTER-Martin-26/11/86 removed initiallization of things not in XWP
06593 
06594 ********************************************************************************************/
06595 
06596 void TranspInfoBarOp::InitControls()
06597 {
06598     // Don't do anything if the Info bar isn't displayed
06599     if (!TranspTool::IsCurrentTool() || !IsVisible()) return;
06600 
06601 //  if (SliderDragged)
06602 //      return;
06603 
06604     SetGadgetRange(_R(IDC_TRANSPSLIDE), 0, SliderMax);
06605 
06606     DeleteAllValues(_R(IDC_GEOMETRY));
06607     DeleteAllValues(_R(IDC_TRANSPTYPE));
06608     DeleteAllValues(_R(IDC_MAPPING));
06609 //  DeleteAllValues(_R(IDC_BITMAPEFFECT));
06610     m_oBitmapDropDown.Init(WindowID, _R(IDC_BITMAPEFFECT));
06611     m_oBitmapDropDown.SetColumns(3);
06612     m_oBitmapDropDown.SetItemSize(wxSize(50, 50));
06613 
06614 
06615     SetGadgetHelp(_R(IDC_GEOMETRY),     _R(IDBBL_TRANSPTOOL_TRANSPSHAPE),   _R(IDS_TRANSPTOOL_TRANSPSHAPE));
06616     SetGadgetHelp(_R(IDC_TRANSPTYPE),   _R(IDBBL_TRANSPTOOL_TRANSPTYPE),    _R(IDS_TRANSPTOOL_TRANSPTYPE));
06617     SetGadgetHelp(_R(IDC_MAPPING),      _R(IDBBL_TRANSPTOOL_TRANSPTILING),  _R(IDS_TRANSPTOOL_TRANSPTILING));
06618     SetGadgetHelp(_R(IDC_BITMAPEFFECT), _R(IDBBL_FILLTOOL_BITMAPNAME),      _R(IDS_FILLTOOL_BITMAPNAME));
06619     SetGadgetHelp(_R(IDC_SELPOINT),     _R(IDBBL_TRANSPTOOL_TRANSPHANDLE),  _R(IDS_TRANSPTOOL_TRANSPHANDLE));
06620     SetGadgetHelp(_R(IDC_TRANSPSLIDE),  _R(IDBBL_TRANSPTOOL_TRANSP),        _R(IDS_TRANSPTOOL_TRANSP));
06621     SetGadgetHelp(_R(IDC_SELCOLOUR),    _R(IDBBL_TRANSPTOOL_TRANSP),        _R(IDS_TRANSPTOOL_TRANSP));
06622 
06623     String_64 Str;
06624 
06625     // Setup the Menu Item text entries
06626     for ( INT32 i=0; i<TransparencyGeometryMenuCount; i++ )
06627     {
06628         Str.Load( TransparencyGeometryMenu[i].StringID );
06629         SetStringGadgetValue( _R(IDC_GEOMETRY), Str, TRUE, TransparencyGeometryMenu[i].Geometry );
06630     }
06631 
06632     Str.Load(_R(IDS_FILLTOOL_PAINT));
06633     SetStringGadgetValue(_R(IDC_TRANSPTYPE),Str,FALSE, FTMENU_REFLECT);
06634     Str.Load(_R(IDS_FILLTOOL_STAIN));
06635     SetStringGadgetValue(_R(IDC_TRANSPTYPE),Str,FALSE, FTMENU_SUB);
06636     Str.Load(_R(IDS_FILLTOOL_BLEACH));
06637     SetStringGadgetValue(_R(IDC_TRANSPTYPE),Str,TRUE, FTMENU_ADD);
06638     Str.Load(_R(IDS_FILLTOOL_CONTRAST));
06639     SetStringGadgetValue(_R(IDC_TRANSPTYPE),Str,TRUE, FTMENU_CON);
06640     Str.Load(_R(IDS_FILLTOOL_SATURATE));
06641     SetStringGadgetValue(_R(IDC_TRANSPTYPE),Str,TRUE, FTMENU_SAT);
06642     Str.Load(_R(IDS_FILLTOOL_DARKEN));
06643     SetStringGadgetValue(_R(IDC_TRANSPTYPE),Str,TRUE, FTMENU_DARK);
06644     Str.Load(_R(IDS_FILLTOOL_LIGHTEN));
06645     SetStringGadgetValue(_R(IDC_TRANSPTYPE),Str,TRUE, FTMENU_LIGHT);
06646     Str.Load(_R(IDS_FILLTOOL_BRIGHTNESS));
06647     SetStringGadgetValue(_R(IDC_TRANSPTYPE),Str,TRUE, FTMENU_BRI);
06648     Str.Load(_R(IDS_FILLTOOL_LUMINOSITY));
06649     SetStringGadgetValue(_R(IDC_TRANSPTYPE),Str,TRUE, FTMENU_LUM);
06650     Str.Load(_R(IDS_FILLTOOL_HUE));
06651     SetStringGadgetValue(_R(IDC_TRANSPTYPE),Str,TRUE, FTMENU_HUE);
06652 
06653     Str.Load(_R(IDS_FILLTOOL_TESS_SIMPLE));
06654     SetStringGadgetValue(_R(IDC_MAPPING),Str,FALSE, FTMENU_SIMPLE);
06655     Str.Load(_R(IDS_FILLTOOL_TESS_REPEAT));
06656     SetStringGadgetValue(_R(IDC_MAPPING),Str,TRUE, FTMENU_REPEAT);
06657     Str.Load(_R(IDS_FILLTOOL_TESS_REPEATINV));
06658     SetStringGadgetValue(_R(IDC_MAPPING),Str,TRUE, FTMENU_REPEATINV);
06659 
06660     // Ensure the drop-downs are the correct length
06661     SetComboListLength(_R(IDC_GEOMETRY));
06662     SetComboListLength(_R(IDC_TRANSPTYPE));
06663     SetComboListLength(_R(IDC_MAPPING));
06664 
06665     SetGadgetWritable(_R(IDC_GEOMETRY), FALSE);
06666     SetGadgetWritable(_R(IDC_TRANSPTYPE), FALSE);
06667     SetGadgetWritable(_R(IDC_MAPPING), FALSE);
06668 
06669     SetGadgetWritable(_R(IDC_SELPOINT), FALSE);
06670     SetGadgetWritable(_R(IDC_SELCOLOUR), TRUE);
06671 
06672     SliderMax = 255;
06673     SetGadgetRange(_R(IDC_TRANSPSLIDE), 0, SliderMax, 1);
06674     SetGadgetBitmaps(_R(IDC_TRANSPSLIDE), _R(IDB_SLIDERBASE), _R(IDB_SLIDERSLIDER));
06675 
06676     // Default to the first items in each list
06677     SelGeometryIndex = FGMENU_LINEARTRANSP;
06678     SelMappingIndex = 0;
06679 
06680     CommonGeometry = NULL;
06681     CommonMapping = NULL;
06682 
06683     MappingDisabled = FALSE;
06684     AllowForceToSimpleMapping = TRUE;
06685 
06686     TypeDisabled = TRUE;
06687 
06688     LastSliderPos = -1; 
06689 
06690     Mode = NOFILL;
06691 
06692     m_BiasGainGadget.Init(this, _R(IDC_BIASGAIN), _R(IDBBL_BIASGAIN),  _R(IDS_BIASGAINDLG));
06693     m_BiasGainGadget.ToggleTranspFillProfile ();
06694 
06695     ShowInfo();
06696 }           
06697 
06698 /********************************************************************************************
06699 
06700 >   void TranspInfoBarOp::ShowInfo()
06701 
06702     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
06703     Created:    9/5/95
06704     Purpose:    Show Transparency Info on the current selection.
06705     SeeAlso:    -
06706 
06707 ********************************************************************************************/
06708 
06709 void TranspInfoBarOp::ShowInfo()
06710 {
06711     // Don't do anything if the Info bar isn't displayed
06712     if (!TranspTool::IsCurrentTool() || !IsVisible()) return;
06713 
06714     // Now have a look at the selected objects
06715     Selection = GetApplication()->FindSelection();
06716 
06717     // Re-Count the number of selected fill control points
06718     AttrFillGeometry::SetSelectionCount(AttrFillGeometry::CountSelectionControlPoints());
06719 
06720     OldMode = Mode;
06721 
06722     ShowCommonType();
06723 
06724     // Now show different info depending on the type ...
06725     // (Well we will do eventually)
06726 
06727     switch (Mode)
06728     {
06729         case NOFILL:
06730             ShowFlatInfo();
06731             break;
06732 
06733         case FLATFILL:
06734             ShowFlatInfo();
06735             break;
06736 
06737         case GRADFILL:
06738         case GRADREPEATFILL:
06739             ShowGraduatedInfo();
06740             break;
06741 
06742         case BITMAPFILL:
06743             ShowBitmapInfo();
06744             break;
06745 
06746         case FRACTALFILL:
06747             ShowFractalInfo();
06748             break;
06749 
06750         case NOISEFILL:
06751             ShowNoiseInfo();
06752             break;
06753 
06754         default:
06755             ShowGraduatedInfo();
06756             break;
06757     }
06758 
06759     EnableControls();
06760 }
06761 
06762 /********************************************************************************************
06763 
06764 >   void TranspInfoBarOp::InitMapping()
06765 
06766     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
06767     Created:    22/8/96
06768     Purpose:    Initialise the Mapping Control.
06769     SeeAlso:    -
06770 
06771 ********************************************************************************************/
06772 
06773 void TranspInfoBarOp::InitMapping()
06774 {
06775     DeleteAllValues(_R(IDC_MAPPING));
06776     EnableGadget(_R(IDC_MAPPING), TRUE);
06777     MappingDisabled = FALSE;
06778 
06779     String_64 Str;
06780 
06781     Str.Load(_R(IDS_FILLTOOL_MAPSIMPLE));
06782     SetStringGadgetValue(_R(IDC_MAPPING), Str,FALSE, FMMENU_SIMPLE);
06783     Str.Load(_R(IDS_FILLTOOL_MAPREPEAT));
06784     SetStringGadgetValue(_R(IDC_MAPPING), Str,TRUE, FMMENU_REPEATING);
06785 
06786     SetComboListLength(_R(IDC_MAPPING));
06787 }
06788 
06789 /********************************************************************************************
06790 
06791 >   void TranspInfoBarOp::InitBitmapName()
06792 
06793     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> (ported to transparency tool by Chris Snook 11/10/99)
06794     Created:    8/5/95
06795     Purpose:    Initialise the Bitmap Name Control.
06796     SeeAlso:    -
06797 
06798 ********************************************************************************************/
06799 
06800 void TranspInfoBarOp::InitBitmapName()
06801 {
06802 //  DeleteAllValues(_R(IDC_BITMAPEFFECT));
06803     m_oBitmapDropDown.Clear();
06804     EnableGadget (_R(IDC_BITMAPEFFECT), TRUE);
06805 
06806     Document* pDoc = Document::GetSelected();
06807 
06808     // Get the bitmap list
06809     BitmapList* Bitmaps = NULL;
06810     if (pDoc) Bitmaps = pDoc->GetBitmapList();
06811 
06812     if (Bitmaps == NULL)
06813         return;
06814 
06815     String_256 Str;
06816 
06817     if (Bitmaps->GetCount() > 0)
06818     {
06819         INT32 Index = 0;
06820 
06821         ListItem* pBmp = Bitmaps->GetHead();
06822 
06823 //      DeleteAllValues ( _R(IDC_BITMAPEFFECT) );
06824 
06825         while (pBmp != NULL)
06826         {
06827             if (!((KernelBitmap*)pBmp)->HasBeenDeleted())   // Ignore deleted bitmaps
06828             {
06829                 Str = ((KernelBitmap*)pBmp)->ActualBitmap->GetName();
06830 
06831                 KernelBitmap* bitmap = ((KernelBitmap*)pBmp);
06832                 m_oBitmapDropDown.AddItem(bitmap, FALSE, Str);
06833                 
06834                 Index++;
06835             }
06836 
06837             pBmp = Bitmaps->GetNext(pBmp);
06838         }
06839 
06840 //      SetComboListLength(_R(IDC_BITMAPEFFECT));
06841     }
06842     //else
06843     //{
06844         // (not sure about this for a custom box)
06845         
06846         //Str.Load(_R(IDS_FILLTOOL_DEFAULTNAME));
06847         //SetStringGadgetValue(_R(IDC_EFFECT),&Str,TRUE, 0);
06848     //}
06849 }
06850 
06851 /********************************************************************************************
06852 
06853 >   void TranspInfoBarOp::InitTransType ()
06854 
06855     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
06856     Created:    8/5/95
06857     Purpose:    Initialise the Transparency Type Control.
06858     SeeAlso:    -
06859 
06860 ********************************************************************************************/
06861 
06862 void TranspInfoBarOp::InitTransType ()
06863 {
06864     DeleteAllValues (_R(IDC_TRANSPTYPE));
06865     EnableGadget (_R(IDC_TRANSPTYPE), TRUE);
06866 
06867     String_64 Str;
06868 
06869     Str.Load(_R(IDS_FILLTOOL_PAINT));
06870     SetStringGadgetValue(_R(IDC_TRANSPTYPE), Str,FALSE, FTMENU_REFLECT);
06871     Str.Load(_R(IDS_FILLTOOL_STAIN));
06872     SetStringGadgetValue(_R(IDC_TRANSPTYPE),Str,FALSE, FTMENU_SUB);
06873     Str.Load(_R(IDS_FILLTOOL_BLEACH));
06874     SetStringGadgetValue(_R(IDC_TRANSPTYPE),Str,TRUE, FTMENU_ADD);
06875     Str.Load(_R(IDS_FILLTOOL_CONTRAST));
06876     SetStringGadgetValue(_R(IDC_TRANSPTYPE),Str,TRUE, FTMENU_CON);
06877     Str.Load(_R(IDS_FILLTOOL_SATURATE));
06878     SetStringGadgetValue(_R(IDC_TRANSPTYPE),Str,TRUE, FTMENU_SAT);
06879     Str.Load(_R(IDS_FILLTOOL_DARKEN));
06880     SetStringGadgetValue(_R(IDC_TRANSPTYPE),Str,TRUE, FTMENU_DARK);
06881     Str.Load(_R(IDS_FILLTOOL_LIGHTEN));
06882     SetStringGadgetValue(_R(IDC_TRANSPTYPE),Str,TRUE, FTMENU_LIGHT);
06883     Str.Load(_R(IDS_FILLTOOL_BRIGHTNESS));
06884     SetStringGadgetValue(_R(IDC_TRANSPTYPE),Str,TRUE, FTMENU_BRI);
06885     Str.Load(_R(IDS_FILLTOOL_LUMINOSITY));
06886     SetStringGadgetValue(_R(IDC_TRANSPTYPE),Str,TRUE, FTMENU_LUM);
06887     Str.Load(_R(IDS_FILLTOOL_HUE));
06888     SetStringGadgetValue(_R(IDC_TRANSPTYPE),Str,TRUE, FTMENU_HUE);
06889 
06890     SetComboListLength(_R(IDC_TRANSPTYPE));
06891 }
06892 
06893 
06894 /********************************************************************************************
06895 
06896 >   void TranspInfoBarOp::InitTesselate()
06897 
06898     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
06899     Created:    8/5/95
06900     Purpose:    Initialise the Tesselation Control.
06901     SeeAlso:    -
06902 
06903 ********************************************************************************************/
06904 
06905 void TranspInfoBarOp::InitTesselate()
06906 {
06907     DeleteAllValues(_R(IDC_MAPPING));
06908     EnableGadget(_R(IDC_MAPPING), TRUE);
06909     MappingDisabled = FALSE;
06910 
06911     String_64 Str;
06912 
06913     Str.Load(_R(IDS_FILLTOOL_TESS_SIMPLE));
06914     SetStringGadgetValue(_R(IDC_MAPPING),Str,FALSE, FTMENU_SIMPLE);
06915     Str.Load(_R(IDS_FILLTOOL_TESS_REPEAT));
06916     SetStringGadgetValue(_R(IDC_MAPPING),Str,TRUE, FTMENU_REPEAT);
06917     Str.Load(_R(IDS_FILLTOOL_TESS_REPEATINV));
06918     SetStringGadgetValue(_R(IDC_MAPPING),Str,TRUE, FTMENU_REPEATINV);
06919 
06920     SetComboListLength(_R(IDC_MAPPING));
06921 }
06922 
06923 /********************************************************************************************
06924 
06925 >   void TranspInfoBarOp::DisplayTransparencyPercentString (double value)
06926 
06927     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
06928     Created:    21/12/99
06929     Inputs:     value - the (double) value that is to be converted/displayed as percent.
06930                 To get the correct results, the value supplied for value MUST be in the
06931                 range 0-255; and NOT 0-100!
06932     Purpose:    Sorts out the transparency value that is actually displayed (as a string).
06933                 It actually calculates the percentage value that has been/ is being applied.
06934                 This is calculated in 0.5% intervals.
06935     SeeAlso:    -
06936 
06937 ********************************************************************************************/
06938 
06939 void TranspInfoBarOp::DisplayTransparencyPercentString (double value)
06940 {
06941     if (value == (double) 1) { value = 0; }         // cause of the way the slider is bodged
06942     
06943     double TranspVal = ((double) value * 100) / (double) SliderMax;
06944 
06945     UINT32 Rounded = (UINT32) TranspVal;
06946     double Diff = TranspVal - Rounded;
06947 
06948     if (Diff < 0.5)
06949     {
06950         if (Diff < 0.25) { TranspVal = (double) Rounded; }
06951         else { TranspVal = (double) Rounded + 0.5; }
06952     }
06953     else
06954     {
06955         if (Diff < 0.75) { TranspVal = (double) Rounded + 0.5; }
06956         else { TranspVal = (double) ++Rounded; }
06957     }
06958 
06959     String_64 Str;
06960 
06961     Convert::DoubleToString( TranspVal, &Str, 1 );
06962 
06963     if (Str.FindNextChar ((TCHAR) '.') == -1)
06964     {
06965         // need to wack a .0 in ....
06966 
06967         Str += _T(".0");
06968     }
06969     
06970     Str.MakePercent ((TCHAR*) Str);
06971 
06972     String_64 PercentStr(Str);
06973     SetGadgetString(_R(IDC_SELCOLOUR), &PercentStr);
06974 }
06975 
06976 /********************************************************************************************
06977 
06978 >   BOOL TranspInfoBarOp::SetGadgetString(CGadgetID Gadget, StringBase* StrValue)
06979 
06980     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
06981     Created:    8/5/95
06982     Purpose:    Set the string displayed by a Gadget.
06983                 This version only updates the gadget if it has changed.
06984     SeeAlso:    -
06985 
06986 ********************************************************************************************/
06987 
06988 BOOL TranspInfoBarOp::SetGadgetString(CGadgetID Gadget, StringBase* StrValue)
06989 {
06990     if (Gadget == _R(IDC_EFFECT) && TypeDisabled)
06991         return TRUE;
06992 
06993     if (Gadget == _R(IDC_MAPPING) && MappingDisabled)
06994         return TRUE;
06995 
06996     if (GetStringGadgetValue(Gadget, NULL, -1) != *StrValue)
06997     {
06998         return SetStringGadgetValue(Gadget, *StrValue, FALSE, -1);
06999     }
07000 
07001     return TRUE;
07002 }
07003 
07004 /********************************************************************************************
07005 
07006 >   void TranspInfoBarOp::ShowFlatInfo()
07007 
07008     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
07009     Created:    20/10/94
07010     Purpose:    Show info on a flat fill.
07011 
07012 ********************************************************************************************/
07013 
07014 void TranspInfoBarOp::ShowFlatInfo()
07015 {
07016     if (OldMode != FLATFILL && OldMode != NOFILL)
07017     {
07018         InitTransType ();
07019         InitTesselate();
07020 //      InitType();
07021 
07022         SetGadgetHelp(_R(IDC_TRANSPTYPE),   _R(IDBBL_TRANSPTOOL_TRANSPTYPE),    _R(IDS_TRANSPTOOL_TRANSPTYPE));
07023         SetGadgetHelp(_R(IDC_MAPPING),      _R(IDBBL_TRANSPTOOL_TRANSPTILING),  _R(IDS_TRANSPTOOL_TRANSPTILING));
07024         SetGadgetHelp(_R(IDC_SELPOINT),     _R(IDBBL_TRANSPTOOL_TRANSPHANDLE),  _R(IDS_TRANSPTOOL_TRANSPHANDLE));
07025         SetGadgetHelp(_R(IDC_TRANSPSLIDE),  _R(IDBBL_TRANSPTOOL_TRANSP),        _R(IDS_TRANSPTOOL_TRANSP));
07026         SetGadgetHelp(_R(IDC_SELCOLOUR),    _R(IDBBL_TRANSPTOOL_TRANSP),        _R(IDS_TRANSPTOOL_TRANSP));
07027 
07028         // Reset the slider back to its proper range as if we have been using the fractal fill
07029         // the the slider range will be large and we will always set 0 tranasparency i.e.
07030         // dragging the slider always gives 0
07031         SliderMax = 255;
07032         SetGadgetRange(_R(IDC_TRANSPSLIDE), 0, SliderMax, 1);
07033     }
07034 
07035     ShowCommonTesselate();
07036     ShowCommonTranspType();
07037     ShowControlPointInfo();
07038 }
07039 
07040 /********************************************************************************************
07041 
07042 >   void TranspInfoBarOp::ShowGraduatedInfo()
07043 
07044     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
07045     Created:    20/10/94
07046     Purpose:    Show info on a graduated fill.
07047 
07048 ********************************************************************************************/
07049 
07050 void TranspInfoBarOp::ShowGraduatedInfo()
07051 {
07052     if (OldMode != GRADFILL && OldMode != GRADREPEATFILL)
07053     {
07054         InitTransType ();
07055         InitMapping();
07056 //      InitType();
07057 
07058         SetGadgetHelp(_R(IDC_TRANSPTYPE),   _R(IDBBL_TRANSPTOOL_TRANSPTYPE),    _R(IDS_TRANSPTOOL_TRANSPTYPE));
07059         SetGadgetHelp(_R(IDC_MAPPING),      _R(IDBBL_TRANSPTOOL_TRANSPTILING),  _R(IDS_TRANSPTOOL_TRANSPTILING));
07060         SetGadgetHelp(_R(IDC_SELPOINT),     _R(IDBBL_TRANSPTOOL_TRANSPHANDLE),  _R(IDS_TRANSPTOOL_TRANSPHANDLE));
07061         SetGadgetHelp(_R(IDC_TRANSPSLIDE),  _R(IDBBL_TRANSPTOOL_TRANSP),        _R(IDS_TRANSPTOOL_TRANSP));
07062         SetGadgetHelp(_R(IDC_SELCOLOUR),    _R(IDBBL_TRANSPTOOL_TRANSP),        _R(IDS_TRANSPTOOL_TRANSP));
07063 
07064         // Reset the slider back to its proper range as if we have been using the fractal fill
07065         // the the slider range will be large and we will always set 0 tranasparency i.e.
07066         // dragging the slider always gives 0
07067         SliderMax = 255;
07068         SetGadgetRange(_R(IDC_TRANSPSLIDE), 0, SliderMax, 1);
07069     }
07070 
07071     ShowCommonMapping();
07072     ShowCommonTranspType();
07073     ShowControlPointInfo();
07074 }
07075 
07076 
07077 /********************************************************************************************
07078 
07079 >   void TranspInfoBarOp::ShowBitmapInfo()
07080 
07081     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
07082     Created:    20/10/94
07083     Purpose:    Show info on a bitmap fill.
07084 
07085 ********************************************************************************************/
07086 
07087 void TranspInfoBarOp::ShowBitmapInfo()
07088 {
07089     if (OldMode != BITMAPFILL)
07090     {
07091         InitTesselate();
07092         InitTransType ();
07093 //      InitType();
07094         InitBitmapName();
07095 
07096         SetGadgetHelp(_R(IDC_TRANSPTYPE),   _R(IDBBL_TRANSPTOOL_TRANSPTYPE),    _R(IDS_TRANSPTOOL_TRANSPTYPE));
07097         SetGadgetHelp(_R(IDC_MAPPING),      _R(IDBBL_TRANSPTOOL_TRANSPTILING),  _R(IDS_TRANSPTOOL_TRANSPTILING));
07098         SetGadgetHelp(_R(IDC_BITMAPEFFECT), _R(IDBBL_FILLTOOL_BITMAPNAME),      _R(IDS_FILLTOOL_BITMAPNAME));
07099     }
07100 
07101     if (AttrFillGeometry::SelectionCount == 0)
07102     {
07103         SetGadgetWritable(_R(IDC_SELPOINT), TRUE);
07104         
07105         SetGadgetHelp(_R(IDC_SELPOINT),     _R(IDBBL_FILLTOOL_FRACTALRES),      _R(IDS_FILLTOOL_FRACTALRES));
07106         //SetGadgetHelp(_R(IDC_TRANSPSLIDE),    _R(IDBBL_TRANSPTOOL_GRAININESS),    _R(IDS_TRANSPTOOL_GRAININESS));
07107         //SetGadgetHelp(_R(IDC_SELCOLOUR),      _R(IDBBL_TRANSPTOOL_GRAININESS),    _R(IDS_TRANSPTOOL_GRAININESS));
07108         SetGadgetHelp(_R(IDC_TRANSPSLIDE),  _R(IDBBL_TRANSPTOOL_TRANSP),        _R(IDS_TRANSPTOOL_TRANSP));
07109         SetGadgetHelp(_R(IDC_SELCOLOUR),    _R(IDBBL_TRANSPTOOL_TRANSP),        _R(IDS_TRANSPTOOL_TRANSP));
07110 
07111         //EnableGadget (_R(IDC_TRANSPSLIDE), FALSE);
07112         //EnableGadget (_R(IDC_SELCOLOUR), FALSE);
07113     }
07114     else
07115     {
07116         SetGadgetWritable(_R(IDC_SELPOINT), FALSE);
07117         SetGadgetHelp(_R(IDC_SELPOINT),     _R(IDBBL_TRANSPTOOL_TRANSPHANDLE),  _R(IDS_TRANSPTOOL_TRANSPHANDLE));
07118 
07119         SetGadgetHelp(_R(IDC_TRANSPSLIDE),  _R(IDBBL_TRANSPTOOL_TRANSP),        _R(IDS_TRANSPTOOL_TRANSP));
07120         SetGadgetHelp(_R(IDC_SELCOLOUR),    _R(IDBBL_TRANSPTOOL_TRANSP),        _R(IDS_TRANSPTOOL_TRANSP));
07121 
07122         SliderMax = 255;
07123     }
07124 
07125     SetGadgetRange(_R(IDC_TRANSPSLIDE), 0, SliderMax, 1);
07126 
07127     ShowCommonTesselate();
07128     ShowCommonTranspType();
07129     ShowCommonBitmapName();
07130 
07131     if (AttrFillGeometry::SelectionCount == 0)
07132         ShowCommonBitmapDpi();
07133 
07134     ShowControlPointInfo();
07135 }
07136 
07137 
07138 /********************************************************************************************
07139 
07140 >   void TranspInfoBarOp::ShowNoiseInfo()
07141 
07142     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
07143     Created:    20/10/94
07144     Purpose:    Show info on a noise transparency
07145 
07146 ********************************************************************************************/
07147 
07148 void TranspInfoBarOp::ShowNoiseInfo()
07149 {
07150     if (OldMode != NOISEFILL)
07151     {
07152         InitTransType ();
07153         InitTesselate();
07154         //InitType();
07155 
07156         SetGadgetHelp(_R(IDC_TRANSPTYPE),   _R(IDBBL_TRANSPTOOL_TRANSPTYPE),    _R(IDS_TRANSPTOOL_TRANSPTYPE));
07157         SetGadgetHelp(_R(IDC_MAPPING),      _R(IDBBL_TRANSPTOOL_TRANSPTILING),  _R(IDS_TRANSPTOOL_TRANSPTILING));
07158     }
07159 
07160     if (AttrFillGeometry::SelectionCount == 0)
07161     {
07162         SetGadgetWritable(_R(IDC_SELPOINT), TRUE);
07163 
07164         SetGadgetHelp(_R(IDC_SELPOINT),     _R(IDBBL_FILLTOOL_FRACTALRES),      _R(IDS_FILLTOOL_FRACTALRES));
07165         SetGadgetHelp(_R(IDC_TRANSPSLIDE),  _R(IDBBL_TRANSPTOOL_NOISESCALE),    _R(IDS_TRANSPTOOL_NOISESCALE));
07166         SetGadgetHelp(_R(IDC_SELCOLOUR),    _R(IDBBL_TRANSPTOOL_NOISESCALE),    _R(IDS_TRANSPTOOL_NOISESCALE));
07167 
07168         SliderMax = GetScalePosMax();
07169     }
07170     else
07171     {
07172         SetGadgetWritable(_R(IDC_SELPOINT), FALSE);
07173 
07174         SetGadgetHelp(_R(IDC_SELPOINT),     _R(IDBBL_TRANSPTOOL_TRANSPHANDLE),  _R(IDS_TRANSPTOOL_TRANSPHANDLE));
07175         SetGadgetHelp(_R(IDC_TRANSPSLIDE),  _R(IDBBL_TRANSPTOOL_TRANSP),        _R(IDS_TRANSPTOOL_TRANSP));
07176         SetGadgetHelp(_R(IDC_SELCOLOUR),    _R(IDBBL_TRANSPTOOL_TRANSP),        _R(IDS_TRANSPTOOL_TRANSP));
07177         
07178         SliderMax = 255;
07179     }
07180 
07181     SetGadgetRange(_R(IDC_TRANSPSLIDE), 0, SliderMax, 1);
07182 
07183     ShowCommonTesselate();
07184     ShowCommonTranspType();
07185 
07186     if (AttrFillGeometry::SelectionCount == 0)
07187     {
07188         ShowCommonBitmapDpi();
07189         ShowCommonNoiseScale();
07190     }
07191     else
07192         ShowControlPointInfo();
07193 }
07194 
07195 /********************************************************************************************
07196 
07197 >   void TranspInfoBarOp::ShowFractalInfo()
07198 
07199     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
07200     Created:    20/10/94
07201     Purpose:    Show info on a fractal transparency
07202 
07203 ********************************************************************************************/
07204 
07205 void TranspInfoBarOp::ShowFractalInfo()
07206 {
07207     if (OldMode != FRACTALFILL)
07208     {
07209         InitTransType ();
07210         InitTesselate();
07211 //      InitType();
07212 
07213         //SetGadgetHelp(_R(IDC_TRANSPTYPE),     _R(IDBBL_TRANSPTOOL_TRANSPTYPE),    _R(IDS_TRANSPTOOL_TRANSPTYPE));
07214         SetGadgetHelp(_R(IDC_MAPPING),      _R(IDBBL_TRANSPTOOL_TRANSPTILING),  _R(IDS_TRANSPTOOL_TRANSPTILING));
07215     }
07216 
07217     if (AttrFillGeometry::SelectionCount == 0)
07218     {
07219         SetGadgetWritable(_R(IDC_SELPOINT), TRUE);
07220         
07221         SetGadgetHelp(_R(IDC_SELPOINT),     _R(IDBBL_FILLTOOL_FRACTALRES),      _R(IDS_FILLTOOL_FRACTALRES));
07222         SetGadgetHelp(_R(IDC_TRANSPSLIDE),  _R(IDBBL_TRANSPTOOL_GRAININESS),    _R(IDS_TRANSPTOOL_GRAININESS));
07223         SetGadgetHelp(_R(IDC_SELCOLOUR),    _R(IDBBL_TRANSPTOOL_GRAININESS),    _R(IDS_TRANSPTOOL_GRAININESS));
07224 
07225         SliderMax = GetGrainPosMax();
07226     }
07227     else
07228     {
07229         SetGadgetWritable(_R(IDC_SELPOINT), FALSE);
07230 
07231         SetGadgetHelp(_R(IDC_SELPOINT),     _R(IDBBL_TRANSPTOOL_TRANSPHANDLE),  _R(IDS_TRANSPTOOL_TRANSPHANDLE));
07232         SetGadgetHelp(_R(IDC_TRANSPSLIDE),  _R(IDBBL_TRANSPTOOL_TRANSP),        _R(IDS_TRANSPTOOL_TRANSP));
07233         SetGadgetHelp(_R(IDC_SELCOLOUR),    _R(IDBBL_TRANSPTOOL_TRANSP),        _R(IDS_TRANSPTOOL_TRANSP));
07234 
07235         SliderMax = 255;
07236     }
07237 
07238     SetGadgetRange(_R(IDC_TRANSPSLIDE), 0, SliderMax, 1);
07239 
07240     ShowCommonTesselate();
07241     ShowCommonTranspType();
07242 
07243     if (AttrFillGeometry::SelectionCount == 0)
07244     {
07245         ShowCommonBitmapDpi();
07246         ShowCommonFractalGrain();
07247     }
07248     else
07249         ShowControlPointInfo();
07250 }
07251 
07252 /********************************************************************************************
07253 
07254 >   void TranspInfoBarOp::ShowCommonType()
07255 
07256     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> (altered by Chris Snook)
07257     Created:    25/8/94
07258     Inputs:     if ShowDataAndNotSet is FALSE, then data members will be set (for controlling
07259                 menu selection logic) and data will not be shown in the relevant control.
07260     Purpose:    Show any Common Fill Type in the selection.
07261 
07262 ********************************************************************************************/
07263 
07264 void TranspInfoBarOp::ShowCommonType(BOOL ShowDataAndNotSet)
07265 {
07266     CommonAttr = SelRange::ATTR_NONE;
07267     String_64 Str;
07268     Str.Load(_R(IDS_FILLTOOL_NONE));
07269     String_64 TStr;
07270     TStr.Load(_R(IDS_FILLTOOL_NONE));
07271 
07272     if (Selection != NULL)
07273     {
07274         Document* pCurrentDoc = Document::GetCurrent();
07275         if (Document::GetSelected())
07276             Document::GetSelected()->SetCurrent();
07277 
07278 EffectsStack* pStack = Selection->GetEffectsStack();
07279 INT32 iStackPos = STACKPOS_TOP;
07280 Range* pLevel = pStack->GetLevelRange(&iStackPos, FALSE);       // Don't escape old controllers, apply attr to base nodes
07281         
07282         // Try and find a common Attribute within the selection.
07283         // All objects in the selection must have an Identical fill for this
07284         // to find anything.
07285 //      CommonAttr = Selection->FindCommonAttribute(CC_RUNTIME_CLASS(AttrTranspFillGeometry), 
07286 //                                                  (NodeAttribute**)&CommonGeometry);
07287         CommonAttr = pLevel->FindCommonAttribute(CC_RUNTIME_CLASS(AttrTranspFillGeometry), 
07288                                                     (NodeAttribute**)&CommonGeometry,
07289                                                     TRUE);
07290         CCRuntimeClass* GeometryType;
07291 
07292         // Try and find a common Attribute Type within the selection.
07293         // The fills need not be identical. Just of the same type.
07294 //      SelRange::CommonAttribResult CommonType = 
07295 //              Selection->FindCommonAttributeType(CC_RUNTIME_CLASS(AttrTranspFillGeometry), 
07296 //                                                  &GeometryType);
07297         SelRange::CommonAttribResult CommonType = 
07298                 pLevel->FindCommonAttributeType(CC_RUNTIME_CLASS(AttrTranspFillGeometry), 
07299                                                     &GeometryType,
07300                                                     FALSE,
07301                                                     TRUE);
07302 
07303         if (CommonAttr == SelRange::ATTR_NONE &&
07304             CommonGeometry != NULL)
07305         {
07306             CommonAttr = SelRange::ATTR_COMMON;
07307         }
07308 
07309         if (CommonType == SelRange::ATTR_NONE &&
07310             GeometryType != NULL)
07311         {
07312             CommonType = SelRange::ATTR_COMMON;
07313         }
07314     
07315         // Make the menu show any Common Fill Type
07316         // or failing that, 'None' or 'Many'.
07317         if (CommonType == SelRange::ATTR_COMMON)
07318         {   
07319             if (GeometryType == CC_RUNTIME_CLASS(AttrFlatTranspFill))
07320             {
07321                 Str.Load(_R(IDS_FILLTOOL_FLATTRANSP));
07322                 Mode = FLATFILL;
07323                 CurrentGeometryIndex = FGMENU_FLATTRANSP;
07324 
07325                 if (CommonAttr == SelRange::ATTR_COMMON)
07326                 {
07327                     if ( (CommonGeometry->GetTranspType() == TT_Mix) && ((*CommonGeometry->GetStartTransp()) == 0) )
07328                     {
07329                         Str.Load(_R(IDS_FILLTOOL_NONE));
07330                         Mode = NOFILL;
07331                         CurrentGeometryIndex = 0;
07332                     }
07333                 }
07334             }
07335             else if (GeometryType == CC_RUNTIME_CLASS(AttrLinearTranspFill))
07336             {
07337                 Str.Load(_R(IDS_FILLTOOL_LINEAR));
07338                 Mode = GRADFILL;
07339                 CurrentGeometryIndex = FGMENU_LINEARTRANSP;
07340             }
07341             else if (GeometryType == CC_RUNTIME_CLASS(AttrCircularTranspFill))
07342             {
07343                 Str.Load(_R(IDS_FILLTOOL_CIRCULAR));
07344                 Mode = GRADFILL;
07345                 CurrentGeometryIndex = FGMENU_CIRCULARTRANSP;
07346             }
07347             else if (GeometryType == CC_RUNTIME_CLASS(AttrRadialTranspFill))
07348             {
07349                 Str.Load(_R(IDS_FILLTOOL_ELLIPTICAL));
07350                 Mode = GRADFILL;
07351                 CurrentGeometryIndex = FGMENU_RADIALTRANSP;
07352             }
07353             else if (GeometryType == CC_RUNTIME_CLASS(AttrConicalTranspFill))
07354             {
07355                 Str.Load(_R(IDS_FILLTOOL_CONICAL));
07356                 Mode = GRADFILL;
07357                 CurrentGeometryIndex = FGMENU_CONICALTRANSP;
07358             }
07359             else if (GeometryType == CC_RUNTIME_CLASS(AttrSquareTranspFill))
07360             {
07361                 Str.Load(_R(IDS_FILLTOOL_SQUARE));
07362                 Mode = GRADFILL;
07363                 CurrentGeometryIndex = FGMENU_SQUARETRANSP;
07364             }
07365             else if (GeometryType == CC_RUNTIME_CLASS(AttrThreeColTranspFill))
07366             {
07367                 Str.Load(_R(IDS_FILLTOOL_THREECOLTRANS));
07368                 Mode = GRADREPEATFILL;
07369                 CurrentGeometryIndex = FGMENU_THREECOLTRANSP;
07370             }
07371             else if (GeometryType == CC_RUNTIME_CLASS(AttrFourColTranspFill))
07372             {
07373                 Str.Load(_R(IDS_FILLTOOL_FOURCOLTRANS));
07374                 Mode = GRADREPEATFILL;
07375                 CurrentGeometryIndex = FGMENU_FOURCOLTRANSP;
07376             }
07377             else if (GeometryType == CC_RUNTIME_CLASS(AttrBitmapTranspFill))
07378             {
07379                 Str.Load(_R(IDS_FILLTOOL_TEXTURE));
07380                 Mode = BITMAPFILL;
07381                 CurrentGeometryIndex = FGMENU_BITMAPTRANSP;
07382             }
07383             else if (GeometryType == CC_RUNTIME_CLASS(AttrFractalTranspFill))
07384             {
07385                 Str.Load(_R(IDS_FILLTOOL_FRACTAL));
07386                 Mode = FRACTALFILL;
07387                 CurrentGeometryIndex = FGMENU_FRACTALTRANSP;
07388             }
07389             else if (GeometryType == CC_RUNTIME_CLASS(AttrNoiseTranspFill))
07390             {
07391                 Str.Load(_R(IDS_FILLTOOL_NOISE));
07392                 Mode = NOISEFILL;
07393                 CurrentGeometryIndex = FGMENU_NOISETRANSP;
07394             }
07395         }
07396         else
07397         {
07398             if (CommonAttr == SelRange::ATTR_MANY)
07399             {
07400                 // There are many different types of fill selected
07401                 Str.Load(_R(IDS_FILLTOOL_MANY));
07402                 Mode = MANYFILLS;
07403                 CurrentGeometryIndex = FGMENU_MANYTRANSP;
07404             }
07405         }
07406 
07407         if (pCurrentDoc)
07408             pCurrentDoc->SetCurrent();
07409     }
07410 
07411     // Update the Menus
07412     if (ShowDataAndNotSet)
07413     {
07414         SetGadgetString(_R(IDC_GEOMETRY),&Str);
07415     }
07416 }
07417 
07418 /********************************************************************************************
07419 
07420 >   void GradInfoBarOp::ShowCommonTranspType ()
07421 
07422     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> (ported to filltool by Chris Snook 11/10/99)
07423     Created:    25/8/94
07424     Inputs:     if ShowDataAndNotSet is FALSE, then data members will be set (for controlling
07425                 menu selection logic) and data will not be shown in the relevant control.
07426     Purpose:    Show any Common Transparency type in the selection.
07427 
07428 ********************************************************************************************/
07429 
07430 void TranspInfoBarOp::ShowCommonTranspType (BOOL ShowDataAndNotSet)
07431 {
07432     String_64 TStr;
07433     TStr.Load (_R(IDS_FILLTOOL_NONE));
07434 
07435     INT32 TType = FindCommonTranspType ();
07436     switch (TType)
07437     {
07438         case -1:
07439             TStr.Load(_R(IDS_FILLTOOL_MANY));
07440             CurrentTransTypeIndex = -2;
07441             break;
07442 
07443         case 0:
07444             TStr.Load(_R(IDS_FILLTOOL_NONE));
07445             CurrentTransTypeIndex = -1;
07446             break;
07447 
07448         case 1:
07449             TStr.Load(_R(IDS_FILLTOOL_PAINT));
07450             CurrentTransTypeIndex = FTMENU_REFLECT;
07451             break;
07452 
07453         case 2:
07454             TStr.Load(_R(IDS_FILLTOOL_STAIN));
07455             CurrentTransTypeIndex = FTMENU_SUB;
07456             break;
07457 
07458         case 3:
07459             TStr.Load(_R(IDS_FILLTOOL_BLEACH));
07460             CurrentTransTypeIndex = FTMENU_ADD;
07461             break;
07462 
07463         case 13:
07464             TStr.Load(_R(IDS_FILLTOOL_CONTRAST));
07465             CurrentTransTypeIndex = FTMENU_CON;
07466             break;
07467 
07468         case 16:
07469             TStr.Load(_R(IDS_FILLTOOL_SATURATE));
07470             CurrentTransTypeIndex = FTMENU_SAT;
07471             break;
07472 
07473         case 19:
07474             TStr.Load(_R(IDS_FILLTOOL_DARKEN));
07475             CurrentTransTypeIndex = FTMENU_DARK;
07476             break;
07477         
07478         case 22:
07479             TStr.Load(_R(IDS_FILLTOOL_LIGHTEN));
07480             CurrentTransTypeIndex = FTMENU_LIGHT;
07481             break;
07482 
07483         case 25:
07484             TStr.Load(_R(IDS_FILLTOOL_BRIGHTNESS));
07485             CurrentTransTypeIndex = FTMENU_BRI;
07486             break;
07487 
07488         case 28:
07489             TStr.Load(_R(IDS_FILLTOOL_LUMINOSITY));
07490             CurrentTransTypeIndex = FTMENU_LUM;
07491             break;
07492 
07493         case 31:
07494             TStr.Load(_R(IDS_FILLTOOL_HUE));
07495             CurrentTransTypeIndex = FTMENU_HUE;
07496             break;
07497     }
07498 
07499     if (ShowDataAndNotSet)
07500     {
07501         SetGadgetString(_R(IDC_TRANSPTYPE),&TStr);
07502     }
07503 }
07504 
07505 /********************************************************************************************
07506 
07507 >   UINT32 TranspInfoBarOp::FindCommonTranspType()
07508 
07509     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> (ported to filltool by Chris Snook 11/10/99)
07510     Created:    14/9/94
07511     Returns:    0 = No Common type, >0 = Common Transparency Type
07512     Purpose:    Tries to find a common transparency type within the selection.
07513                 This now makes use of camelots new AttrPaintingMode (which I also wrote).
07514 
07515 ********************************************************************************************/
07516 
07517 INT32 TranspInfoBarOp::FindCommonTranspType()
07518 {
07519     if (Selection->Count() == 0)
07520     {
07521         AttrFillGeometry* pCurrentFill = GetCurrentGeometry();
07522 
07523         if (pCurrentFill != NULL)
07524         {
07525             return pCurrentFill->GetTranspType();
07526         }
07527 
07528         return 0;
07529     }
07530 
07531     AttrFillGeometry* pAttrNode = AttrFillGeometry::FindFirstSelectedAttr(CC_RUNTIME_CLASS(AttrTranspFillGeometry));
07532 
07533     // Return if there aren't any
07534     if (pAttrNode == NULL)
07535         return 0;
07536 
07537     UINT32 TType = 0;
07538     
07539     while (pAttrNode != NULL)
07540     {
07541         if (pAttrNode->GetAttributeType() == CC_RUNTIME_CLASS(AttrTranspFillGeometry))
07542         {
07543             UINT32 NodeTType = pAttrNode->GetTranspType();
07544             
07545             if (TType == 0)
07546                 TType = NodeTType;
07547 
07548             if (TType != NodeTType)
07549                 return -1;
07550         }
07551 
07552         // Check the next fill
07553         pAttrNode = AttrFillGeometry::FindNextSelectedAttr(CC_RUNTIME_CLASS(AttrTranspFillGeometry));
07554     }
07555 
07556     return TType;
07557 }
07558 
07559 
07560 /********************************************************************************************
07561 
07562 >   void GradInfoBarOp::ShowCommonMapping()
07563 
07564     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com> (altered by Chris Snook)
07565     Created:    22/8/96
07566     Inputs:     if ShowDataAndNotSet is FALSE, then data members will be set (for controlling
07567                 menu selection logic) and data will not be shown in the relevant control.
07568     Purpose:    Show any Common Fill Mapping in the selection.
07569 
07570 ********************************************************************************************/
07571 
07572 void TranspInfoBarOp::ShowCommonMapping(BOOL ShowDataAndNotSet)
07573 {
07574     String_64 Str;
07575 
07576     INT32 CommTess = FindCommonTesselate();
07577 
07578     switch (CommTess)
07579     {
07580         case -1:
07581             Str.Load(_R(IDS_FILLTOOL_MANY));
07582             CurrentMappingIndex = -2;//FMMENU_REPEATING;
07583             break;
07584 
07585         case 0:
07586             Str.Load(_R(IDS_FILLTOOL_NONE));
07587             CurrentMappingIndex = -1;//FMMENU_REPEATING;
07588             break;
07589 
07590         case 1:
07591             Str.Load(_R(IDS_FILLTOOL_MAPSIMPLE));
07592             CurrentMappingIndex = FMMENU_SIMPLE;
07593             break;
07594 
07595         case 2:
07596 //Mark Howitt, 14/10/97. Lets make sure repeating trans grad fills when set to 2 are actually simple!
07597 #ifdef NEW_FEATURES
07598             if(Mode == GRADFILL)
07599             {
07600                 Str.Load(_R(IDS_FILLTOOL_MAPSIMPLE));
07601                 CurrentMappingIndex = FMMENU_SIMPLE;
07602                 break;
07603             }
07604             else
07605             {
07606                 Str.Load(_R(IDS_FILLTOOL_MAPREPEAT));
07607                 CurrentMappingIndex = FMMENU_REPEATING;
07608                 break;
07609             }
07610         case 4:     // Must be a repeating trans grad fill!
07611 #endif
07612         case 3:
07613             Str.Load(_R(IDS_FILLTOOL_MAPREPEAT));
07614             CurrentMappingIndex = 2;//FMMENU_REPEATING;
07615             break;
07616     }
07617 
07618     if (ShowDataAndNotSet)
07619     {
07620         SetGadgetString(_R(IDC_MAPPING),&Str);
07621     }
07622 }
07623 
07624 /********************************************************************************************
07625 
07626 >   void TranspInfoBarOp::ShowCommonTesselate()
07627 
07628     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
07629     Created:    25/8/94
07630     Purpose:    Show any Common Fill Tesselation in the selection.
07631 
07632 ********************************************************************************************/
07633 
07634 void TranspInfoBarOp::ShowCommonTesselate()
07635 {
07636     String_64 Str;
07637 
07638     INT32 CommTess = FindCommonTesselate();
07639 
07640     switch (CommTess)
07641     {
07642         case -1:
07643             Str.Load(_R(IDS_FILLTOOL_MANY));
07644             CurrentMappingIndex = FTMENU_REPEAT;
07645             break;
07646 
07647         case 0:
07648             Str.Load(_R(IDS_FILLTOOL_NONE));
07649             CurrentMappingIndex = FTMENU_REPEAT;
07650             break;
07651 
07652         case 1:
07653             Str.Load(_R(IDS_FILLTOOL_TESS_SIMPLE));
07654             CurrentMappingIndex = FTMENU_SIMPLE;
07655             break;
07656 
07657         case 2:
07658             Str.Load(_R(IDS_FILLTOOL_TESS_REPEAT));
07659             CurrentMappingIndex = FTMENU_REPEAT;
07660             break;
07661 
07662         case 3:
07663             Str.Load(_R(IDS_FILLTOOL_TESS_REPEATINV));
07664             CurrentMappingIndex = FTMENU_REPEATINV;
07665             break;
07666     }
07667 
07668     SetGadgetString(_R(IDC_MAPPING),&Str);
07669 //  SetStringGadgetValue(_R(IDC_MAPPING),&Str, FALSE, -1);
07670     EnableGadget(_R(IDC_MAPPING), TRUE);
07671 }
07672 
07673 /********************************************************************************************
07674 
07675 >   INT32 TranspInfoBarOp::FindCommonTesselate()
07676 
07677     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
07678     Created:    25/8/94
07679     Purpose:    Find any Common Fill Tesselation in the selection.
07680 
07681 ********************************************************************************************/
07682 
07683 INT32 TranspInfoBarOp::FindCommonTesselate()
07684 {
07685     INT32 CommonTess = 0;
07686     Node* pNode;
07687     NodeAttribute* pChild;
07688 
07689     if (Selection->Count() == 0)
07690     {
07691         AttrTranspFillMapping* pCurrentMapping = GetCurrentMapping();
07692 
07693         if (pCurrentMapping != NULL)
07694         {
07695             return pCurrentMapping->GetRepeat();
07696         }
07697 
07698         return 0;
07699     }
07700 
07701     // Are there any selected Objects ?
07702     if (Selection != NULL)
07703     {
07704 EffectsStack* pStack = Selection->GetEffectsStack();
07705 INT32 iStackPos = STACKPOS_TOP;
07706 Range* pLevel = pStack->GetLevelRange(&iStackPos, FALSE);       // Don't escape old controllers, apply attr to base nodes
07707         // Find the first Object
07708 /*      pNode = Selection->FindFirst();
07709         while (pNode != NULL)
07710         {
07711             BOOL FoundAttr = ((NodeRenderableInk*)pNode)->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrTranspFillMapping), &pChild);
07712             
07713             if (FoundAttr)
07714             {
07715                 INT32 Tess = ((AttrTranspFillMapping*)pChild)->GetRepeat();
07716 
07717                 if (CommonTess == 0)
07718                     CommonTess = Tess;
07719 
07720                 if (Tess != CommonTess)
07721                 {
07722                     return -1; // Many
07723                 }
07724             }
07725 
07726             pNode = Selection->FindNext(pNode);
07727         }
07728 */
07729         pNode = pLevel->FindFirst();
07730         while (pNode != NULL)
07731         {
07732             pChild = ((NodeRenderableInk*)pNode)->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrTranspFillMapping));
07733             
07734             if (pChild)
07735             {
07736                 INT32 Tess = ((AttrTranspFillMapping*)pChild)->GetRepeat();
07737 
07738                 if (CommonTess == 0)
07739                     CommonTess = Tess;
07740 
07741                 if (Tess != CommonTess)
07742                 {
07743                     return -1; // Many
07744                 }
07745             }
07746 
07747             pNode = pLevel->FindNext(pNode);
07748         }
07749 
07750     }
07751 
07752     //if (CommonTess == 0)
07753     //  return RT_Repeating;
07754 
07755     return CommonTess;
07756 }
07757 
07758 /********************************************************************************************
07759 
07760 >   void TranspInfoBarOp::ShowCommonBitmapName()
07761 
07762     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
07763     Created:    25/8/94
07764     Purpose:    Show any Common Bitmap Name in the selection.
07765 
07766 ********************************************************************************************/
07767 
07768 void TranspInfoBarOp::ShowCommonBitmapName()
07769 {
07770     String_64 strName = FindCommonBitmapName();
07771     m_oBitmapDropDown.SelectByLabel(strName);
07772 }
07773 
07774 /********************************************************************************************
07775 
07776 >   String_64 TranspInfoBarOp::FindCommonBitmapName()
07777 
07778     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
07779     Created:    25/8/94
07780     Purpose:    Find any Common Bitmap Name in the selection.
07781 
07782 ********************************************************************************************/
07783 
07784 String_64 TranspInfoBarOp::FindCommonBitmapName()
07785 {
07786     String_256 CommonName;
07787     CommonName.Load(_R(IDS_FILLTOOL_NONE));
07788 
07789     if (Selection->Count() == 0)
07790     {
07791         AttrFillGeometry* pCurrentFill = GetCurrentGeometry();
07792 
07793         //AttrTranspFillGeometry* pCurrentFill = GetCurrentGeometry();
07794 
07795         // NOTE:  we can call either IsATranspFill or IsABitmapFill here ....
07796         // BOTH return TRUE, the only difference is that IsABitmapFill is a base
07797         // class member function (AttrBitmapFill::) and IsATranspFill is a 'true'
07798         // class function (i.e.  defined and implemented in AttrBitmapTranspFill)
07799         // BUT, lets stick with IsABitmapFill (for clarity) - cause after all,
07800         // were dealing with bitmaps here ....
07801 
07802         if (pCurrentFill && pCurrentFill->/*IsATranspFill*/IsABitmapFill())
07803         {
07804             CommonName = pCurrentFill->GetBitmap()->ActualBitmap->GetName();
07805         }
07806 
07807         return CommonName;
07808     }
07809 
07810     String_256 Name;
07811     Name.Load(_R(IDS_FILLTOOL_NONE));
07812     
07813     String_256 None;
07814     None.Load(_R(IDS_FILLTOOL_NONE));
07815 
07816     String_256 Many;
07817     Many.Load(_R(IDS_FILLTOOL_MANY));
07818 
07819     // Find the first Fill Attribute in the selection (of the right type!)
07820     // (observe the CC_RUNTIME_CLASS(AttrTranspFillGeometry) 
07821     AttrFillGeometry* pAttrNode = AttrTranspFillGeometry::FindFirstSelectedAttr(CC_RUNTIME_CLASS(AttrTranspFillGeometry));
07822 
07823     // Return if there aren't any
07824     if (pAttrNode == NULL)
07825         return None;
07826 
07827     while (pAttrNode != NULL)
07828     {
07829         if (pAttrNode->IsKindOf(CC_RUNTIME_CLASS(AttrBitmapTranspFill)))
07830         {
07831             Name = pAttrNode->GetBitmap()->ActualBitmap->GetName();
07832 
07833             if (CommonName == None)
07834                 CommonName = Name;
07835 
07836             if (Name != CommonName)
07837             {
07838                 return Many;
07839             }
07840         }
07841 
07842         // Check the next fill (of the right type!)
07843         pAttrNode = AttrTranspFillGeometry::FindNextSelectedAttr(CC_RUNTIME_CLASS(AttrTranspFillGeometry));
07844     }
07845 
07846     return CommonName;
07847 }
07848 
07849 /********************************************************************************************
07850 
07851 >   void TranspInfoBarOp::ShowCommonBitmapDpi()
07852 
07853     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
07854     Created:    25/8/94
07855     Purpose:    Show any Common Bitmap Dpi in the selection.
07856 
07857 ********************************************************************************************/
07858 
07859 void TranspInfoBarOp::ShowCommonBitmapDpi()
07860 {
07861     INT32 dpi = FindCommonBitmapDpi();
07862 
07863     TCHAR Str[16];
07864     String_64 DpiStr;
07865 
07866     if (dpi == 0)
07867     {
07868         DpiStr.Load(_R(IDS_FILLTOOL_NODPI));
07869     }
07870 
07871     else if (dpi == -1)
07872     {
07873         DpiStr.Load(_R(IDS_FILLTOOL_MANYDPI));
07874     }
07875 
07876     else if (dpi > 0)
07877     {
07878         String_256 jcf(_R(IDS_FILLTOOL_DPI_FORMAT));
07879         camSnprintf(Str, 15, jcf, (INT32) dpi);
07880         DpiStr = Str;
07881     }
07882 
07883     SetGadgetString(_R(IDC_SELPOINT), &DpiStr);
07884 }
07885 
07886 void TranspInfoBarOp::SetGadgetWritable(INT32 id, BOOL enable)
07887 {
07888     PORTNOTETRACE("other","TranspInfoBarOp::SetGadgetWritable disabled");
07889 #ifndef EXCLUDE_FROM_XARALX
07890     // Bodge code to try and make a gadget writable on the fly
07891     HWND gadget = ::GetDlgItem(WindowID, id);
07892     HWND hEdit = ::ChildWindowFromPoint(gadget, CPoint(1,1));
07893 
07894     if (hEdit)
07895         gadget = hEdit;
07896  
07897     if (enable)
07898         ::SendMessage(gadget, EM_SETREADONLY, FALSE, 0);
07899     else
07900         ::SendMessage(gadget, EM_SETREADONLY, TRUE, 0);
07901 #endif
07902 }
07903 
07904 /********************************************************************************************
07905 
07906 >   BOOL TranspInfoBarOp::GetGadgetWritable(INT32 id)
07907 
07908     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
07909     Created:    6/11/99
07910     Inputs:     id, the 'IDC_?' of the control.
07911     Returns:    TRUE if writable, FALSE otherwise
07912     Purpose:    Returns whether the control is writable (i.e.  read only, or not).
07913                 void TranspInfoBarOp::EnableControls() needs to make use of this to control
07914                 its 'dynamic' toolbar correctly (both of which were also written by me).
07915 
07916 ********************************************************************************************/
07917 
07918 BOOL TranspInfoBarOp::GetGadgetWritable (INT32 id)
07919 {
07920     PORTNOTETRACE("other","TranspInfoBarOp::GetGadgetWritable disabled");
07921 #ifndef EXCLUDE_FROM_XARALX
07922     // Get the window handle of the gadget, from the gadget ID
07923     HWND gadget = ::GetDlgItem (WindowID, id);
07924 
07925     // See if it's got a child window (it may be a Combo Box)
07926     HWND hEdit = ::ChildWindowFromPoint (gadget, CPoint(1,1));
07927 
07928     if (hEdit)              // Was there a child window ?
07929         gadget = hEdit;     // Yes, so send the message to it
07930 
07931     if (GetWindowLong (gadget, GWL_STYLE) & ES_READONLY)
07932     {
07933         return (TRUE);
07934     }
07935     else
07936     {
07937         return (FALSE);
07938     }
07939 #else
07940     return TRUE;
07941 #endif
07942 }
07943 
07944 /********************************************************************************************
07945 
07946 >   INT32 TranspInfoBarOp::FindCommonBitmapDpi()
07947 
07948     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
07949     Created:    25/8/94
07950     Purpose:    Find any Common Bitmap Dpi in the selection.
07951 
07952 ********************************************************************************************/
07953 
07954 INT32 TranspInfoBarOp::FindCommonBitmapDpi()
07955 {
07956     if (Selection->Count() == 0)
07957     {
07958         AttrFillGeometry* pCurrentFill = GetCurrentGeometry();
07959 
07960         if (pCurrentFill && pCurrentFill->IsABitmapFill())
07961         {
07962             return pCurrentFill->GetDPI();
07963         }
07964 
07965         return 0;
07966     }
07967 
07968     // Find the first Fill Attribute in the selection
07969     AttrFillGeometry* pAttrNode = AttrFillGeometry::FindFirstSelectedAttr(CC_RUNTIME_CLASS(AttrTranspFillGeometry));
07970 
07971     // Return if there aren't any
07972     if (pAttrNode == NULL)
07973         return 0;
07974 
07975     INT32 CommonDpi = 0;
07976     INT32 Dpi = 0;
07977 
07978     while (pAttrNode != NULL)
07979     {
07980         if (pAttrNode->IsKindOf(CC_RUNTIME_CLASS(AttrBitmapFill)))
07981         {
07982             if (pAttrNode->IsKindOf(CC_RUNTIME_CLASS(AttrTextureTranspFill)) ||
07983                 pAttrNode->IsKindOf(CC_RUNTIME_CLASS(AttrBitmapTranspFill))  )
07984             {
07985                 Dpi = pAttrNode->GetDPI();
07986 
07987                 if (CommonDpi == 0)
07988                     CommonDpi = Dpi;
07989 
07990                 if (Dpi != CommonDpi)
07991                 {
07992                     return -1; // Many
07993                 }
07994             }
07995         }
07996 
07997         // Check the next fill
07998         pAttrNode = AttrFillGeometry::FindNextSelectedAttr(CC_RUNTIME_CLASS(AttrTranspFillGeometry));
07999     }
08000 
08001     return CommonDpi;
08002 }
08003 
08004 /********************************************************************************************
08005 
08006 >   void TranspInfoBarOp::ShowCommonFractalGrain()
08007 
08008     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
08009     Created:    25/8/94
08010     Purpose:    Show any Common Fractal Graininess in the selection.
08011 
08012 ********************************************************************************************/
08013 
08014 void TranspInfoBarOp::ShowCommonFractalGrain()
08015 {
08016     double Grain = FindCommonFractalGrain();
08017 
08018     TCHAR Str[16];
08019     String_64 GrainStr;
08020 
08021     if (Grain == 0)
08022         GrainStr.Load(_R(IDS_FILLTOOL_NOGRAIN));
08023     if (Grain == -1)
08024         GrainStr.Load(_R(IDS_FILLTOOL_MANYGRAIN));
08025     if (Grain > 0)
08026     {
08027         camSnprintf(Str, 15, _T("%.1f"), Grain);
08028         GrainStr = Str;
08029     }
08030 
08031     INT32 GrainPos = GetGrainPos(Grain);
08032 
08033     SetGadgetString(_R(IDC_SELCOLOUR),&GrainStr);
08034     SetLongGadgetValue(_R(IDC_TRANSPSLIDE), GrainPos);
08035 
08036     // Build the Percentage string and set it
08037     camSnprintf(Str, 15, _T("%.1f"), Grain);
08038     String_8 PercentStr(Str);
08039     SetGadgetString(_R(IDC_SELCOLOUR), &PercentStr);
08040 }
08041 
08042 /********************************************************************************************
08043 
08044 >   FIXED16 TranspInfoBarOp::FindCommonFractalGrain()
08045 
08046     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
08047     Created:    25/8/94
08048     Purpose:    Find any Common Fractal Graininess in the selection.
08049 
08050 ********************************************************************************************/
08051 
08052 double TranspInfoBarOp::FindCommonFractalGrain()
08053 {
08054     if (Selection->Count() == 0)
08055     {
08056         AttrFillGeometry* pCurrentFill = GetCurrentGeometry();
08057 
08058         if (pCurrentFill && pCurrentFill->IsAFractalFill())
08059         {
08060             return ((FractalTranspFillAttribute*)pCurrentFill->GetAttributeValue())->Graininess.MakeDouble();
08061         }
08062 
08063         return 0;
08064     }
08065 
08066     // Find the first Fill Attribute in the selection
08067     AttrFillGeometry* pAttrNode = AttrFillGeometry::FindFirstSelectedAttr(CC_RUNTIME_CLASS(AttrTranspFillGeometry));
08068 
08069     // Return if there aren't any
08070     if (pAttrNode == NULL)
08071         return 0;
08072 
08073     double CommonGrain = 0;
08074 
08075     while (pAttrNode != NULL)
08076     {
08077         if (pAttrNode->IsKindOf(CC_RUNTIME_CLASS(AttrFractalTranspFill)))
08078         {
08079             double Grain = ((FractalTranspFillAttribute*)pAttrNode->GetAttributeValue())->Graininess.MakeDouble();
08080 
08081             if (CommonGrain == 0)
08082                 CommonGrain = Grain;
08083 
08084             if (Grain != CommonGrain)
08085             {
08086                 return -1; // Many
08087             }
08088         }
08089 
08090         // Check the next fill
08091         pAttrNode = AttrFillGeometry::FindNextSelectedAttr(CC_RUNTIME_CLASS(AttrTranspFillGeometry));
08092     }
08093 
08094     return CommonGrain;
08095 }
08096 
08097 /********************************************************************************************
08098 
08099 >   void TranspInfoBarOp::ShowCommonNoiseScale()
08100 
08101     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
08102     Created:    25/8/94
08103     Purpose:    Show any Common Fractal Graininess in the selection.
08104 
08105 ********************************************************************************************/
08106 
08107 void TranspInfoBarOp::ShowCommonNoiseScale()
08108 {
08109     double Scale = FindCommonNoiseScale();
08110 
08111     BOOL convert = FALSE;
08112 
08113     TCHAR Str[16];
08114     String_64 ScaleStr;
08115 
08116     if (Scale == 0)
08117     {
08118         ScaleStr.Load(_R(IDS_FILLTOOL_NOGRAIN));
08119     }
08120     if (Scale == -1)
08121     {
08122         ScaleStr.Load(_R(IDS_FILLTOOL_MANYGRAIN));
08123     }
08124     if (Scale > 0)
08125     {   
08126         camSnprintf(Str, 15, _T("%.1f"), Scale);
08127         ScaleStr = Str;
08128         convert = TRUE;
08129     }
08130 
08131     INT32 ScalePos = GetScalePos(Scale);
08132 
08133     SetGadgetString(_R(IDC_SELCOLOUR),&ScaleStr);
08134     SetLongGadgetValue(_R(IDC_TRANSPSLIDE), ScalePos);
08135 
08136     // Build the Percentage string and set it
08137 
08138     if (convert)
08139     {
08140         String_64 Str;
08141 
08142         Convert::DoubleToString( Scale, &Str, 1 );
08143         
08144         Str.MakePercent ((TCHAR*) Str);
08145 
08146         String_64 PercentStr(Str);
08147         SetGadgetString(_R(IDC_SELCOLOUR), &PercentStr);
08148     }
08149     else
08150     {
08151     
08152         camSnprintf(Str, 15, _T("%.1f"), Scale);
08153         String_8 PercentStr(Str);
08154         SetGadgetString(_R(IDC_SELCOLOUR), &PercentStr);
08155     }
08156 }
08157 
08158 /********************************************************************************************
08159 
08160 >   FIXED16 TranspInfoBarOp::FindCommonNoiseScale()
08161 
08162     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
08163     Created:    25/8/94
08164     Purpose:    Find any Common Noise Scale in the selection.
08165 
08166 ********************************************************************************************/
08167 
08168 double TranspInfoBarOp::FindCommonNoiseScale()
08169 {
08170     if (Selection->Count() == 0)
08171     {
08172         AttrFillGeometry* pCurrentFill = GetCurrentGeometry();
08173 
08174         if (pCurrentFill && IS_A(pCurrentFill, AttrNoiseTranspFill))
08175         {
08176             return ((FractalTranspFillAttribute*)pCurrentFill->GetAttributeValue())->GetGraininess().MakeDouble();
08177         }
08178 
08179         return 0;
08180     }
08181 
08182     // Find the first Fill Attribute in the selection
08183     AttrFillGeometry* pAttrNode = AttrFillGeometry::FindFirstSelectedAttr(CC_RUNTIME_CLASS(AttrTranspFillGeometry));
08184 
08185     // Return if there aren't any
08186     if (pAttrNode == NULL)
08187         return 0;
08188 
08189     double CommonScale = 0;
08190 
08191     while (pAttrNode != NULL)
08192     {
08193         if (pAttrNode->IsKindOf(CC_RUNTIME_CLASS(AttrNoiseTranspFill)))
08194         {
08195             double Scale = ((FractalTranspFillAttribute*)pAttrNode->GetAttributeValue())->GetGraininess().MakeDouble();
08196 
08197             if (CommonScale == 0)
08198                 CommonScale = Scale;
08199 
08200             if (Scale != CommonScale)
08201             {
08202                 return -1; // Many
08203             }
08204         }
08205 
08206         // Check the next fill
08207         pAttrNode = AttrFillGeometry::FindNextSelectedAttr(CC_RUNTIME_CLASS(AttrTranspFillGeometry));
08208     }
08209 
08210     return CommonScale;
08211 }
08212 
08213 /********************************************************************************************
08214 
08215 >   void TranspInfoBarOp::ShowControlPointInfo()
08216 
08217     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
08218     Created:    3/8/94
08219     Purpose:    Show Info about selected control points.
08220 
08221 ********************************************************************************************/
08222 
08223 void TranspInfoBarOp::ShowControlPointInfo()
08224 {   
08225     String_64 PointStr;
08226     INT32 Transp;
08227 
08228     // Look though the selection for any selected control points
08229     ScanSelectionForControlPoints(&PointStr, &Transp);
08230 
08231     // PointStr and ColourStr will be updated if we find any
08232 
08233     if (Transp > 255) Transp = 255;
08234     if (Transp < 0)   Transp = 0;
08235 
08236     // Show the selected control points state
08237     if ((Mode != BITMAPFILL && 
08238          Mode != FRACTALFILL &&
08239          Mode != NOISEFILL) ||  AttrFillGeometry::SelectionCount > 0)
08240     {   
08241         SetGadgetString(_R(IDC_SELPOINT), &PointStr);
08242     }
08243 
08244     //TRACEUSER( "Chris", _T("Set slider to Trans = %d\n"), Transp);
08245     SetLongGadgetValue(_R(IDC_TRANSPSLIDE), Transp);
08246     //double TempNewVal = ((double) Transp * 100) / (double) SliderMax;
08247     DisplayTransparencyPercentString ((double) Transp); // and display it
08248 
08249     //INT32 Percent = (Transp * 100) / SliderMax;
08250     //String_64 Str;
08251 
08252     /*double TempNewVal = ((double) Transp * 100) / (double) SliderMax;
08253     String_64 Str;
08254 
08255     Convert::DoubleToString( TempNewVal, &Str, 1 );
08256 
08257     if (Str.FindNextChar ((TCHAR) '.') == -1)
08258     {
08259         // need to wack a .0 in ....
08260 
08261         Str += ".0";
08262     }
08263     
08264     Str.MakePercent ((TCHAR*) Str);
08265 
08266     String_64 PercentStr(Str);
08267     SetGadgetString(_R(IDC_SELCOLOUR), &PercentStr);*/
08268 }
08269 
08270 /********************************************************************************************
08271 
08272 >   void TranspInfoBarOp::ScanSelectionForControlPoints(String_64* PointString, 
08273                                                         String_64* ColourString)
08274     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
08275     Created:    3/8/94
08276     Purpose:    Look for selected control points within the selection.
08277 
08278 ********************************************************************************************/
08279 
08280 void TranspInfoBarOp::ScanSelectionForControlPoints(String_64* PointString, INT32* Transp)
08281 {
08282     *PointString = _T("");
08283     *Transp = -1;
08284 
08285     // Find the first Fill Attribute in the selection
08286     AttrFillGeometry* pAttrNode;
08287     UINT32 count = Selection->Count();
08288 
08289     // Find the first Fill Attribute in the selection
08290     if (count == 0)
08291     {
08292         pAttrNode = GetCurrentGeometry();
08293     }
08294     else
08295     {
08296         pAttrNode = AttrFillGeometry::FindFirstSelectedAttr(CC_RUNTIME_CLASS(AttrTranspFillGeometry));
08297     }
08298 
08299     AllowForceToSimpleMapping = TRUE;
08300 
08301     // Return if there aren't any
08302     if (pAttrNode == NULL)
08303     {
08304         (*PointString).Load(_R(IDS_FILLTOOL_NONE));
08305         *Transp = 0;
08306         return;
08307     }
08308     
08309     INT32 SelCount = 0;
08310     BOOL CommonTransp = TRUE;
08311     BOOL CommonPoint  = TRUE;
08312 
08313     BOOL AllFlat = TRUE;
08314     BOOL AnyNeedSimple = FALSE;
08315 
08316     while (pAttrNode != NULL)
08317     {
08318         if (AttrFillGeometry::FillSelectionCount() > 0)
08319         {
08320             if (!(pAttrNode->GetRuntimeClass() == CC_RUNTIME_CLASS(AttrFlatTranspFill)))
08321             {
08322                 // Get the selection state and colours of this fill
08323                 String_64 PointStr = GetSelectedPoint(pAttrNode);
08324                 UINT32 HandleTransp  = GetSelectedTransp(pAttrNode);
08325 
08326                 String_64 Str;
08327                 Str.Load(_R(IDS_FILLTOOL_NONE));
08328 
08329                 // Where there any points selected ?
08330                 if (PointStr != Str)
08331                 {
08332                     // Update and keep a count
08333                     *PointString = PointStr;
08334                     SelCount++;
08335 
08336                     if (*PointString == String_64(_T("")))
08337                         *PointString = PointStr;
08338 
08339                     if (*PointString != PointStr)
08340                         CommonPoint = FALSE;
08341 
08342                     if (*Transp == -1)
08343                         *Transp = HandleTransp;
08344 
08345                     if (*Transp != INT32(HandleTransp))
08346                         CommonTransp = FALSE;
08347     
08348                     AllFlat = FALSE;
08349                 }
08350             }
08351         }
08352         else 
08353         {
08354             if (pAttrNode->GetRuntimeClass() == CC_RUNTIME_CLASS(AttrFlatTranspFill))
08355             {
08356                 if ( !((pAttrNode->GetTranspType() == TT_Mix) && ((*pAttrNode->GetStartTransp()) == 0)) )
08357                 {
08358                     (*PointString).Load(_R(IDS_FILLTOOL_FLATTRANSP));
08359 
08360                     if (*Transp == -1)
08361                         *Transp = *pAttrNode->GetStartTransp();
08362 
08363                     if (*Transp != INT32(*pAttrNode->GetStartTransp()))
08364                         CommonTransp = FALSE;
08365 
08366                     SelCount++;
08367                 }
08368             }
08369             else
08370             {
08371                 if (SelCount > 0)
08372                     AllFlat = FALSE;
08373             }
08374         }
08375 
08376         // If this is a transp fill attribute and doesn't need simple mapping then set FALSE
08377         if (pAttrNode->IsATranspFill() && pAttrNode->NeedsForceToSimpleMapping())
08378             AnyNeedSimple = TRUE;
08379             
08380         // Check the next fill
08381         if (count > 0)
08382             pAttrNode = AttrFillGeometry::FindNextSelectedAttr(CC_RUNTIME_CLASS(AttrTranspFillGeometry));
08383         else
08384             pAttrNode = NULL;
08385     }
08386 
08387     if (AnyNeedSimple)
08388         AllowForceToSimpleMapping = FALSE;
08389 
08390     if (AttrFillGeometry::FillSelectionCount() == 0 && !AllFlat)
08391     {
08392         (*PointString).Load(_R(IDS_FILLTOOL_MANY));
08393     }
08394 
08395     if (SelCount == 0)
08396     {
08397         // Status indicating many points selected
08398         (*PointString).Load(_R(IDS_FILLTOOL_NONE));
08399     }
08400 
08401     // Was there more than one fill with points selected ?
08402     if (!CommonPoint)
08403     {
08404         // Status indicating many points selected
08405         (*PointString).Load(_R(IDS_FILLTOOL_MANY));
08406     }
08407 
08408     if (!CommonTransp)
08409     {
08410         *Transp = 0;
08411     }
08412 }
08413 
08414 /********************************************************************************************
08415 
08416 >   String_64 TranspInfoBarOp::GetSelectedPoint(AttrFillGeometry* pGeometry)
08417 
08418     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
08419     Created:    9/8/94
08420     Inputs:     -
08421     Outputs:    -
08422     Returns:    A String_64, "None", "Many", or "Start Colour", "End Colour" etc.
08423     Purpose:    Gets a textual description of a fills contol point selection state.
08424 
08425 ********************************************************************************************/
08426 
08427 String_64 TranspInfoBarOp::GetSelectedPoint(AttrFillGeometry* pGeometry)
08428 {
08429     String_64 Str;
08430 
08431     // how many happen to be selected at the moment?
08432     UINT32 SelCount = pGeometry->GetSelectionCount();
08433 
08434     // if there's nothing selected then we're done
08435     if (SelCount<1)
08436     {
08437         Str.Load(_R(IDS_FILLTOOL_NONE));
08438         return Str;
08439     }
08440 
08441     // more than one?   
08442     if (SelCount>1)
08443     {
08444         Str.Load(_R(IDS_FILLTOOL_MANY));
08445         return Str;
08446     }
08447 
08448     // ramp blobs have negative indexes
08449     INT32 i = pGeometry->GetFirstSelectedIndex();
08450     if (ISA_RAMPINDEX(i))
08451     {
08452         Str.Load(_R(IDS_FILLTOOL_RAMPTRANSP));
08453         return Str;
08454     }
08455 
08456     // ok its an end blob so which one is it?
08457     switch (i)
08458     {
08459         case FILLCONTROL_STARTPOINT:
08460             Str.Load(_R(IDS_FILLTOOL_STARTTRANS));
08461             break;
08462 
08463         case FILLCONTROL_ENDPOINT:
08464         case FILLCONTROL_SECONDARYPOINT:
08465             Str.Load(_R(IDS_FILLTOOL_ENDTRANS));
08466             break;
08467 
08468         case FILLCONTROL_ENDPOINT2:
08469             Str.Load(_R(IDS_FILLTOOL_ENDTRANS2));
08470             break;
08471 
08472         case FILLCONTROL_ENDPOINT3:
08473             Str.Load(_R(IDS_FILLTOOL_ENDTRANS3));
08474             break;
08475 
08476         default:
08477             Str.Load(_R(IDS_FILLTOOL_NONE));
08478             break;
08479     }
08480 
08481     return Str;
08482 }
08483 
08484 
08485 /*
08486 String_64 TranspInfoBarOp::GetSelectedPoint(AttrFillGeometry* pGeometry)
08487 {
08488     BOOL SelState[5];
08489     String_64 Str;
08490 
08491     // Get the selection state of this fills control points
08492     pGeometry->GetSelectionState(SelState, 5);
08493 
08494     INT32 SelCount = 0;
08495     for (INT32 i=0; i<5; i++)
08496     {
08497         // Is this point selected ?
08498         if (SelState[i])
08499         {
08500             // Get a description of the Point
08501             switch (i)
08502             {
08503                 case FILLCONTROL_STARTPOINT:
08504                     Str.Load(_R(IDS_FILLTOOL_STARTTRANS));
08505                     break;
08506 
08507                 case FILLCONTROL_ENDPOINT:
08508                     Str.Load(_R(IDS_FILLTOOL_ENDTRANS));
08509                     break;
08510 
08511                 case FILLCONTROL_ENDPOINT2:
08512                     Str.Load(_R(IDS_FILLTOOL_ENDTRANS2));
08513                     break;
08514 
08515                 case FILLCONTROL_ENDPOINT3:
08516                     Str.Load(_R(IDS_FILLTOOL_ENDTRANS3));
08517                     break;
08518 
08519                 case FILLCONTROL_SECONDARYPOINT:
08520                     Str.Load(_R(IDS_FILLTOOL_ENDTRANS));
08521                     break;
08522             }
08523             // Keep a count of how many points were selected
08524             SelCount++;
08525         }
08526     }
08527 
08528     if (SelCount == 0)
08529         Str.Load(_R(IDS_FILLTOOL_NONE));    // No control points were selected
08530 
08531     if (SelCount > 1)
08532         Str.Load(_R(IDS_FILLTOOL_MANY));    // Many control points were selected
08533 
08534     return Str;
08535 }
08536 */
08537 
08538 /********************************************************************************************
08539 
08540 >   String_64 TranspInfoBarOp::GetSelectedColour(AttrFillGeometry* pGeometry)
08541 
08542     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
08543     Created:    9/8/94
08544     Inputs:     -
08545     Outputs:    -
08546     Returns:    A String_64, "None", "Many", or "Colour Name".
08547     Purpose:    Gets a textual description of a fills contol point colour.
08548 
08549 ********************************************************************************************/
08550 
08551 UINT32 TranspInfoBarOp::GetSelectedTransp(AttrFillGeometry* pGeometry)
08552 {
08553     UINT32* pStartTransp = pGeometry->GetStartTransp();
08554     if (pStartTransp == NULL)
08555         return 0;   // Not a transparency fill !
08556 
08557     UINT32* pEndTransp = pGeometry->GetEndTransp();
08558     UINT32 SelCount = pGeometry->GetSelectionCount();
08559 
08560     // if there's nothing selected then we're done
08561     if (SelCount<1)
08562         return 0;
08563 
08564     if (SelCount>1)
08565     {
08566         if (pEndTransp!=NULL && ((*pStartTransp) != (*pEndTransp)))
08567             return 0;
08568     }
08569 
08570     // ok, only one thing selected so go get it
08571     pStartTransp = pGeometry->GetFirstSelectedTransp();
08572     if (pStartTransp)
08573         return (*pStartTransp);
08574 
08575     return 0;
08576 }
08577 
08578 /********************************************************************************************
08579 
08580 >   void TranspInfoBarOp::EnableControls()
08581 
08582     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> (rewritten by Chris Snook)
08583     Created:    3/8/94
08584     Inputs:     -
08585     Outputs:    -
08586     Returns:    -
08587     Purpose:    Enables or disables the controls depending on the current context, i.e.
08588                 the controls are disabled if there is no selection, etc.
08589                 Actually more complicated than this now, cause my function calls now hide/show
08590                 various controls; and dynamically reshuffle the infobar.
08591 
08592 ********************************************************************************************/
08593 
08594 void TranspInfoBarOp::EnableControls()
08595 {
08596     // DMc - check for nodes which transparency can't be applied to
08597     BOOL allowed = TRUE;
08598 
08599     SelRange * pSel = GetApplication()->FindSelection();
08600 
08601     Node * pNode = pSel->FindFirst(FALSE);
08602 
08603     while (pNode && allowed)
08604     {
08605         if (pNode->IsKindOf(CC_RUNTIME_CLASS(NodeShadow)))
08606         {
08607             allowed = FALSE;
08608         }
08609 
08610         pNode = pSel->FindNext(pNode, FALSE);
08611     }
08612     
08613     if (Document::GetSelected() == NULL || !allowed)
08614     {
08615         EnableGadget (_R(IDC_GEOMETRY),     FALSE);
08616         EnableGadget (_R(IDC_MAPPING),      FALSE);
08617         EnableGadget(_R(IDC_TRANSPTYPE),    FALSE);
08618         EnableGadget (_R(IDC_BITMAPEFFECT), FALSE);
08619         EnableGadget (_R(IDC_BIASGAIN),     FALSE);
08620         EnableGadget (_R(IDC_SELPOINT),     FALSE);
08621         EnableGadget (_R(IDC_TRANSPSLIDE),  FALSE);
08622         EnableGadget (_R(IDC_SELCOLOUR),    FALSE);
08623         //EnableGadget(_R(IDC_GRADCOORDS),  FALSE);
08624     }
08625     else
08626     {
08627 
08628         EnableGadget (_R(IDC_GEOMETRY), TRUE);
08629         EnableGadget (_R(IDC_TRANSPTYPE),   TRUE);
08630         EnableGadget (_R(IDC_TRANSPSLIDE), TRUE);
08631         EnableGadget (_R(IDC_SELCOLOUR), TRUE);
08632                 
08633         switch (Mode)
08634         {
08635             case NOFILL:
08636 
08637                 EnableGadget (_R(IDC_MAPPING), FALSE);
08638                 EnableGadget (_R(IDC_BITMAPEFFECT), FALSE);
08639                 EnableGadget (_R(IDC_BIASGAIN), FALSE);
08640                 EnableGadget (_R(IDC_SELPOINT), FALSE);
08641                 EnableGadget (_R(IDC_TRANSPSLIDE), TRUE);
08642                 EnableGadget (_R(IDC_SELCOLOUR), TRUE);
08643             break;
08644             
08645             case MANYFILLS:
08646             case FLATFILL:
08647                 // nothing else to enable ....
08648                 EnableGadget (_R(IDC_MAPPING), FALSE);
08649                 EnableGadget (_R(IDC_BITMAPEFFECT), FALSE);
08650                 EnableGadget (_R(IDC_BIASGAIN), FALSE);
08651                 EnableGadget (_R(IDC_SELPOINT), FALSE);
08652 
08653                 if (Mode == MANYFILLS)
08654                 {
08655                     EnableGadget (_R(IDC_TRANSPSLIDE), FALSE);
08656                     EnableGadget (_R(IDC_SELCOLOUR), FALSE);
08657                 }
08658 
08659                 CloseProfileDialog (m_BiasGainGadget);      // cause fill type cannot be profiled!
08660             break;
08661 
08662             case GRADFILL:
08663             case GRADREPEATFILL:
08664                 switch (CurrentGeometryIndex)
08665                 {
08666                     case FGMENU_LINEARTRANSP:
08667                     case FGMENU_CIRCULARTRANSP:
08668                     case FGMENU_RADIALTRANSP:
08669                     // the following is really fg_diamond ....
08670                     case FGMENU_SQUARETRANSP:
08671 
08672                         EnableGadget (_R(IDC_MAPPING), TRUE);
08673                         EnableGadget (_R(IDC_BITMAPEFFECT), FALSE);
08674 
08675                         //if (2 colour)
08676                         //{
08677                             EnableGadget (_R(IDC_BIASGAIN), TRUE);
08678                         //}
08679                         //else
08680                         //{
08681                         //  EnableGadget (_R(IDC_BIASGAIN), FALSE);
08682                         //}
08683 
08684                         EnableGadget (_R(IDC_SELPOINT), FALSE);
08685                     break;
08686                     
08687                     case FGMENU_CONICALTRANSP:
08688                         EnableGadget (_R(IDC_MAPPING), FALSE);
08689                         EnableGadget (_R(IDC_BITMAPEFFECT), FALSE);
08690 
08691                         //if (2 colour)
08692                         //{
08693                             EnableGadget (_R(IDC_BIASGAIN), TRUE);
08694                         //}
08695                         //else
08696                         //{
08697                         //  EnableGadget (_R(IDC_BIASGAIN), FALSE);
08698                         //}
08699                         
08700                         EnableGadget (_R(IDC_SELPOINT), FALSE);
08701                     break;
08702                     
08703                     case FGMENU_THREECOLTRANSP:
08704                     case FGMENU_FOURCOLTRANSP:
08705                         EnableGadget (_R(IDC_MAPPING), TRUE);
08706                         EnableGadget (_R(IDC_BITMAPEFFECT), FALSE);
08707                         EnableGadget (_R(IDC_BIASGAIN), FALSE);
08708                         EnableGadget (_R(IDC_SELPOINT), FALSE);
08709                     break;
08710                 }
08711             break;
08712 
08713             case BITMAPFILL:
08714                 EnableGadget (_R(IDC_MAPPING), TRUE);
08715                 EnableGadget (_R(IDC_BITMAPEFFECT), TRUE);
08716 
08717                 if (AttrFillGeometry::SelectionCount == 0)
08718                 {
08719                     EnableGadget (_R(IDC_TRANSPSLIDE), FALSE);
08720                     EnableGadget (_R(IDC_SELCOLOUR), FALSE);
08721                 }
08722                 
08723                 //if (2 colour)
08724                 //{
08725                     //EnableGadget (_R(IDC_BIASGAIN), TRUE);
08726                 //}
08727                 //else
08728                 //{
08729                     EnableGadget (_R(IDC_BIASGAIN), TRUE);//FALSE);
08730                 //}
08731 
08732                 //EnableGadget (_R(IDC_SELPOINT), FALSE);
08733 
08734                 if (GetGadgetWritable (_R(IDC_SELPOINT)))
08735                 {
08736                     EnableGadget (_R(IDC_SELPOINT), FALSE);
08737                 }
08738                 else
08739                 {
08740                     EnableGadget (_R(IDC_SELPOINT), TRUE);
08741                 }
08742             break;
08743 
08744             case FRACTALFILL:
08745             case NOISEFILL:
08746                 EnableGadget (_R(IDC_MAPPING), TRUE);
08747                 EnableGadget (_R(IDC_BITMAPEFFECT), FALSE);
08748 
08749                 //if (2 colour)
08750                 //{
08751                     //EnableGadget (_R(IDC_BIASGAIN), TRUE);
08752                 //}
08753                 //else
08754                 //{
08755                     EnableGadget (_R(IDC_BIASGAIN), TRUE);//FALSE);
08756                 //}
08757 
08758                 if (GetGadgetWritable (_R(IDC_SELPOINT)))
08759                 {
08760                     EnableGadget (_R(IDC_SELPOINT), FALSE);
08761                 }
08762                 else
08763                 {
08764                     EnableGadget (_R(IDC_SELPOINT), TRUE);
08765                 }
08766                 
08767                 /*if (GetGadgetWritable (_R(IDC_SELCOLOUR)))
08768                 {
08769                     EnableGadget (_R(IDC_SELCOLOUR), FALSE);
08770                 }
08771                 else
08772                 {
08773                     EnableGadget (_R(IDC_SELCOLOUR), TRUE);
08774                 }*/
08775             break;
08776 
08777             default:
08778             break;
08779         }
08780 
08781 
08782 /*      BOOL enable = TRUE;
08783         EnableGadget(_R(IDC_GEOMETRY),      enable);
08784 
08785 //      if (Mode == NOFILL)
08786 //          enable = FALSE;
08787 
08788         if (TypeDisabled == enable)
08789         {
08790             TypeDisabled = !enable;
08791             //EnableGadget(_R(IDC_TRANSPTYPE),  enable);
08792         }
08793 
08794         enable = FALSE;
08795         if (Mode == BITMAPFILL || 
08796             Mode == FRACTALFILL || 
08797             Mode == GRADREPEATFILL ||
08798 //Mark Howitt, 14/10/97. Implement repeating transparent grad fills, except conical
08799 #ifdef NEW_FEATURES
08800             (Mode == GRADFILL && CurrentGeometryIndex != FGMENU_CONICALTRANSP) ||
08801 #endif
08802             Mode == NOISEFILL)
08803         {
08804             enable = TRUE;
08805         }
08806 
08807         if (MappingDisabled == enable)
08808         {
08809             MappingDisabled = !enable;
08810             EnableGadget(_R(IDC_MAPPING),       enable);
08811         }
08812 
08813 //      if (CommonAttr != SelRange::ATTR_NONE)
08814             enable = TRUE;
08815 //      else
08816 //          enable = FALSE;
08817 
08818         EnableGadget(_R(IDC_SELPOINT),      enable);
08819         EnableGadget(_R(IDC_TRANSPSLIDE),   enable);
08820     //  EnableGadget(_R(IDC_SELPOINT2),     enable);
08821     //  EnableGadget(_R(IDC_SELCOLOUR),     enable);
08822     //  EnableGadget(_R(IDC_SELCOLOURBLOB), enable);
08823 
08824     //  enable = FALSE;
08825     //  EnableGadget(_R(IDC_GRADCOORDS),    enable);
08826     //  EnableGadget(_R(IDC_GRADCOORDS2),   enable);*/
08827     }
08828 
08829 }           
08830 
08831 /********************************************************************************************
08832 
08833 >   void TranspInfoBarOp::SetTranspValue(UINT32 Transp, BOOL bIntermediateStep = FALSE, BOOL bFirstStep = FALSE)
08834 
08835     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
08836     Created:    1/9/94
08837     Purpose:    Called when a the transparency slider is changed.
08838 
08839 ********************************************************************************************/
08840 
08841 void TranspInfoBarOp::SetTranspValue(UINT32 Transp, BOOL bIntermediateStep, BOOL bFirstStep)
08842 {
08843 /*  AttrValueChange* NewTransp = new AttrTranspChange;
08844     if (NewTransp == NULL)
08845     {
08846         InformError();
08847         return;
08848     }
08849 
08850     NewTransp->SetStartTransp(&Transp);
08851 
08852     Operation::SetQuickRender(bIntermediateStep);
08853 
08854         AttributeManager::AttributeSelected(NULL, NewTransp, bIntermediateStep, bFirstStep);
08855 
08856     Operation::SetQuickRender(FALSE);
08857 */
08858 
08859     if (bFirstStep)
08860     {
08861         // ---------------------------------------------
08862         // Drag starting
08863         ERROR3IF(m_pAttrApplyOp!=NULL, "Why do we have a drag op already?\n");
08864         if (m_pAttrApplyOp==NULL)
08865         {
08866             m_pDragTransp = new AttrTranspChange;
08867             if (m_pDragTransp == NULL)
08868                 return;
08869 
08870             m_pDragTransp->SetStartTransp(&Transp);
08871 
08872             m_pAttrApplyOp = new OpApplyAttrInteractive;
08873             m_pAttrApplyOp->DoDragAttr(m_pDragTransp);              // Drag starting
08874             ERROR3IF(m_pAttrApplyOp!=Operation::GetCurrentDragOp(),
08875                      "DoDragAttr should have set itself as the current drag op");
08876         }
08877     }
08878     else if (bIntermediateStep)
08879     {
08880         // ---------------------------------------------
08881         // Drag running
08882         m_pDragTransp->SetStartTransp(&Transp);
08883 
08884         ERROR3IF(m_pAttrApplyOp==NULL, "Why don't we have a drag op yet?\n");
08885         if (m_pAttrApplyOp && m_pAttrApplyOp==Operation::GetCurrentDragOp())
08886             m_pAttrApplyOp->DragAttrChanged(m_pDragTransp);         // Drag running
08887 
08888     }
08889     else
08890     {
08891         // ---------------------------------------------
08892         // Drag ending (or single-click or too many objects to drag interactively)
08893         if (m_pAttrApplyOp==NULL)
08894         {
08895             m_pDragTransp = new AttrTranspChange;
08896             if (m_pDragTransp == NULL)
08897                 return;
08898 
08899             m_pDragTransp->SetStartTransp(&Transp);
08900 
08901             m_pAttrApplyOp = new OpApplyAttrInteractive;
08902             m_pAttrApplyOp->DoDragAttr(m_pDragTransp);              // Drag starting
08903         }
08904 
08905         m_pDragTransp->SetStartTransp(&Transp);
08906 
08907         ERROR3IF(m_pAttrApplyOp==NULL, "Why don't we have a drag op yet?\n");
08908         if (m_pAttrApplyOp)
08909             if (m_pAttrApplyOp==Operation::GetCurrentDragOp())
08910             {
08911                 m_pAttrApplyOp->DragAttrFinished(m_pDragTransp);        // Drag over
08912                 // Don't delete the op - it lives in the undo history now!
08913                 // delete m_pAttrApplyOp;
08914                 // But do release ownership so that we can start another one
08915                 m_pAttrApplyOp = NULL;
08916             }
08917             else
08918             {
08919                 // Drag op must have been cancelled and deleted already (because
08920                 // CurrentDragOp is NULL)
08921                 ShowInfo();                     // Update UI
08922                 m_pAttrApplyOp = NULL;          // Release invalid pointer
08923             }
08924 
08925         if (m_pDragTransp)
08926         {
08927             delete m_pDragTransp;
08928             m_pDragTransp = NULL;
08929         }
08930     }
08931 }
08932 
08933 /********************************************************************************************
08934 
08935 >   void TranspInfoBarOp::ChangeFillType()
08936 
08937     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
08938     Created:    3/8/94
08939     Purpose:    Called when a new fill type is selected from the menu.
08940 
08941 ********************************************************************************************/
08942 
08943 //if (Selection->Count() == 0)
08944     //{
08945     //  AttrFillGeometry* pCurrentFill = GetCurrentGeometry();
08946 
08947         //AttrTranspFillGeometry* pCurrentFill = GetCurrentGeometry();
08948 
08949         // NOTE:  we can call either IsATranspFill or IsABitmapFill here ....
08950         // BOTH return TRUE, the only difference is that IsABitmapFill is a base
08951         // class member function (AttrBitmapFill::) and IsATranspFill is a 'true'
08952         // class function (i.e.  defined and implemented in AttrBitmapTranspFill)
08953         // BUT, lets stick with IsABitmapFill (for clarity) - cause after all,
08954         // were dealing with bitmaps here ....
08955 
08956     //  if (pCurrentFill && pCurrentFill->/*IsATranspFill*/IsABitmapFill())
08957     /*  {
08958             CommonName = pCurrentFill->GetBitmap()->ActualBitmap->GetName();
08959         }
08960 
08961         return CommonName;
08962     }
08963 
08964     String_256 Name;
08965     Name.Load(_R(IDS_FILLTOOL_NONE));
08966     
08967     String_256 None;
08968     None.Load(_R(IDS_FILLTOOL_NONE));
08969 
08970     String_256 Many;
08971     Many.Load(_R(IDS_FILLTOOL_MANY));
08972 
08973     // Find the first Fill Attribute in the selection (of the right type!)
08974     // (observe the CC_RUNTIME_CLASS(AttrTranspFillGeometry) 
08975     AttrFillGeometry* pAttrNode = AttrTranspFillGeometry::FindFirstSelectedAttr (CC_RUNTIME_CLASS(AttrTranspFillGeometry));
08976 
08977     // Return if there aren't any
08978     if (pAttrNode == NULL)
08979         return None;
08980 
08981     while (pAttrNode != NULL)
08982     {
08983         if (pAttrNode->IsKindOf(CC_RUNTIME_CLASS(AttrBitmapTranspFill)))
08984         {
08985             Name = pAttrNode->GetBitmap()->ActualBitmap->GetName();
08986 
08987             if (CommonName == None)
08988                 CommonName = Name;
08989 
08990             if (Name != CommonName)
08991             {
08992                 return Many;
08993             }
08994         }
08995 
08996         // Check the next fill (of the right type!)
08997         pAttrNode = AttrTranspFillGeometry::FindNextSelectedAttr(CC_RUNTIME_CLASS(AttrTranspFillGeometry));
08998     }
08999 
09000     return CommonName;*/
09001 
09002 void TranspInfoBarOp::ChangeFillType()
09003 {
09004     if (CurrentGeometryIndex == FGMENU_NOTRANSP)
09005     {
09006         AttrFillGeometry* NoTransp = new AttrRemoveTransp;
09007         if (NoTransp == NULL)
09008 
09009         {
09010             InformError();
09011             return;
09012         }
09013 
09014         AttributeManager::AttributeSelected(NULL, NoTransp);
09015     }   
09016     else if (CurrentGeometryIndex == FGMENU_FLATTRANSP)
09017     {
09018         AttrFillGeometry* FlatTransp = new AttrMakeFlatTransp;
09019         if (FlatTransp == NULL)
09020         {
09021             InformError();
09022             return;
09023         }
09024 
09025         AttributeManager::AttributeSelected(NULL, FlatTransp);
09026     }   
09027     else
09028     {
09029         // Get the current fill type, and pass a new fill of that type into
09030         // the attribute manager, as a mutator.
09031         AttrFillGeometry* Mutator = MakeFillMutator();
09032         if (Mutator == NULL)
09033         {
09034             InformError();
09035             return;
09036         }
09037 
09038         // If the mutator requires a simple mapping but the current fill doesn't
09039         // then we need to set ForceToSimple to TRUE
09040 
09041         //BOOL ForceToSimple = Mutator->NeedsForceToSimpleMapping() && AllowForceToSimpleMapping;
09042 
09043         // This call deletes the Mutator so I'll set the pointer to NULL
09044         AttributeManager::AttributeSelected(NULL, Mutator);
09045         Mutator = NULL;
09046 
09047         //if (ForceToSimple)
09048         //{
09049     //      CurrentMappingIndex = FMMENU_SIMPLE;
09050     //      ChangeFillMapping ();           // we push two bits of undo here, but this is
09051                                             // unavoidable at present ....
09052         //}
09053     }
09054 
09055     if (CurrentGeometryIndex != FGMENU_NOTRANSP)
09056         UpdateBrushAttributes();
09057 }
09058 
09059 /********************************************************************************************
09060 
09061 >   void TranspInfoBarOp::ChangeFillMapping()
09062 
09063     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
09064     Created:    3/11/94
09065     Purpose:    Called when a new fill mapping or tesselation is selected from the menu.
09066 
09067 ********************************************************************************************/
09068 
09069 void TranspInfoBarOp::ChangeFillMapping()
09070 {
09071     if (Mode != BITMAPFILL && 
09072         Mode != FRACTALFILL && 
09073         Mode != GRADREPEATFILL &&
09074 //Mark Howitt, 14/10/97. Exclude transparent grad fills as well
09075 #ifdef NEW_FEATURES
09076         Mode != GRADFILL &&
09077 #endif
09078         Mode != NOISEFILL)
09079     {
09080         return;
09081     }
09082 
09083     INT32 Tesselation;
09084 
09085     switch (CurrentMappingIndex)
09086     {
09087         case (FTMENU_SIMPLE):
09088             Tesselation = 1;
09089             break;
09090     
09091         case (FTMENU_REPEAT):
09092 //Mark Howitt, 14/10/97. Repeating grad fills are now 4.
09093 #ifdef NEW_FEATURES
09094             if(Mode == GRADFILL)
09095             {
09096                 Tesselation = 4;
09097             }
09098             else
09099 #endif
09100             {
09101                 Tesselation = 2;
09102             }
09103             break;
09104 
09105         case (FTMENU_REPEATINV):
09106             Tesselation = 3;
09107             break;
09108 
09109         default:
09110             Tesselation = 1;
09111             break;
09112     }
09113 
09114     AttrTranspFillMappingLinear* NewMapping = new AttrTranspFillMappingLinear;
09115     if (NewMapping == NULL)
09116     {
09117         InformError();
09118         return;
09119     }
09120 
09121     NewMapping->SetRepeat(Tesselation);
09122     AttributeManager::AttributeSelected(NewMapping, NULL);
09123 }
09124 
09125 
09126 /********************************************************************************************
09127 
09128 >   void TranspInfoBarOp::UpdateBrushAttributes()
09129 
09130     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
09131     Created:    4/3/2000
09132     Purpose:    Called when a new transparency is selected.  This function goes through all
09133                 brush attributes in the selection and tells them to use the local transparency
09134                 rather than their cached one.
09135 
09136 ********************************************************************************************/
09137 
09138 void TranspInfoBarOp::UpdateBrushAttributes()
09139 {
09140     List BrushList;
09141 //  BevelTools::BuildListOfSelectedNodes(&BrushList, CC_RUNTIME_CLASS(AttrBrushType));
09142     FillTools::GetSelectedAttrList(&BrushList, CC_RUNTIME_CLASS(AttrBrushType), FALSE, FALSE);
09143 
09144     NodeListItem* pItem = (NodeListItem*)BrushList.GetHead();
09145     AttrBrushType* pAttrBrush = NULL;
09146     while (pItem != NULL)
09147     {
09148         pAttrBrush = (AttrBrushType*)(pItem->pNode);
09149         if (pAttrBrush != NULL)
09150             pAttrBrush->SetUseLocalTransp(TRUE);
09151 
09152         pItem = (NodeListItem*)BrushList.GetNext(pItem);
09153     }
09154 
09155     BrushList.DeleteAll();
09156 }
09157 
09158 /********************************************************************************************
09159 
09160 >   void TranspInfoBarOp::ChangeBitmapName()
09161 
09162     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> (ported to the transparency tool by Chris Snook 12/10/99)
09163     Created:    14/12/94
09164     Purpose:    Called when a new bitmap is selected from the menu.
09165 
09166 ********************************************************************************************/
09167 
09168 BOOL TranspInfoBarOp::ChangeBitmapName()
09169 {
09170     NodeAttribute *Attrib = new AttrBitmapTranspFill;
09171     if (Attrib == NULL)
09172     {
09173         InformError();
09174         return (FALSE);
09175     }
09176 
09177     Document* pDoc = Document::GetSelected();
09178 
09179     // Get the bitmap list
09180     BitmapList* Bitmaps = NULL;
09181     if (pDoc) Bitmaps = pDoc->GetBitmapList();
09182 
09183     if (Bitmaps == NULL)
09184         return (FALSE);
09185 
09186     INT32 BmpIndex = -1;
09187     ListItem* pBmp = Bitmaps->GetHead();
09188 
09189     while (pBmp != NULL)
09190     {
09191         if (!((KernelBitmap*)pBmp)->HasBeenDeleted())
09192             BmpIndex++;
09193 
09194         if (BmpIndex == CurrentBitmapIndex)
09195             break;
09196 
09197         pBmp = Bitmaps->GetNext(pBmp);
09198     }
09199 
09200     KernelBitmap* pkBmp = (KernelBitmap*) pBmp;
09201 
09202     // CGS:  check for a 32-bit bitmap being applied here as a transparency, since we convert
09203     // this permantly to 24-bit we should ask the user if they wish to continue ....
09204 
09205     if (pkBmp->ActualBitmap->GetBitmapInfoHeader()->biBitCount == 32)
09206     {
09207         // Ask the user wether or not they want to use a 24bit copy of the BMP or use the Default Bitmap?
09208         //InformWarning(_R(IDS_BFX_BMP_CONVERT_MSG),_R(IDS_OK),0,0,0,1,2);
09209 
09210         // Load and build the question text.
09211         String_256 QueryString(_R(IDS_QUERYTRANSP321));
09212                     
09213         // The only way of bringing up a box with a string in it
09214         Error::SetError(0, QueryString, 0);
09215         INT32 DlgResult = InformMessage(FALSE, _R(IDS_YES), _R(IDS_NO));
09216         Error::ClearError();
09217 
09218         switch (DlgResult)
09219         {
09220             case 1:             // YES
09221                                 // apply attribute ....
09222             break;
09223             case 2:             // NO
09224                 delete (Attrib);
09225                 Attrib = NULL;
09226                 return (FALSE);         // break out of this stuff!
09227         }
09228     }
09229 
09230     ((AttrBitmapChange*)Attrib)->AttachBitmap((KernelBitmap*)pBmp);
09231     AttributeManager::AttributeSelected(NULL, Attrib);
09232 
09233     return (TRUE);
09234 }
09235 
09236 /********************************************************************************************
09237 
09238 >   void TranspInfoBarOp::ChangeTranspType()
09239 
09240     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
09241     Created:    3/8/94
09242     Purpose:    Called when a new fill type is selected from the menu.
09243 
09244 ********************************************************************************************/
09245 
09246 void TranspInfoBarOp::ChangeTranspType()
09247 {
09248     // Get the current fill type, and pass a new fill of that type into
09249     // the attribute manager, as a mutator.
09250     AttrFillGeometry* TypeChange = new AttrTranspTypeChange();
09251 
09252     
09253     //AttrPaintingMode* TypeChange = new AttrPaintingMode ();
09254     //AttrTranspTypeChange* TypeChnage = new AttrTranspTypeChange ();
09255     if (TypeChange == NULL)
09256     {
09257         InformError();
09258         return;
09259     }
09260 
09261     UINT32 TType = GetTranspType() - 1;
09262     UINT32 Index = 0;
09263     
09264     switch(TType)
09265     {
09266     case FTMENU_REFLECT:
09267     case FTMENU_SUB:
09268     case FTMENU_ADD:
09269         {
09270             Index = TType + TT_Mix;
09271             break;
09272         }
09273     case FTMENU_CON:
09274         {
09275             Index = TT_CONTRAST;
09276             break;
09277         }
09278     case FTMENU_SAT:
09279         {
09280             Index = TT_SATURATION;
09281             break;
09282         }
09283     case FTMENU_DARK:
09284         {
09285             Index = TT_DARKEN;
09286             break;
09287         }
09288     case FTMENU_LIGHT:
09289         {
09290             Index = TT_LIGHTEN;
09291             break;
09292         }
09293     case FTMENU_BRI:
09294         {
09295             Index = TT_BRIGHTNESS;
09296             break;
09297         }
09298     case FTMENU_LUM:
09299         {
09300             Index = TT_LUMINOSITY;
09301             break;
09302         }
09303     case FTMENU_HUE:
09304         {
09305             Index = TT_HUE;
09306             break;
09307         }
09308     default:
09309         {
09310             Index = TT_NoTranspType;
09311         }
09312     }
09313 
09314     TypeChange->SetTranspType(Index);
09315 
09316     //TypeChange->SetValue (Index);
09317 
09318     //AttributeManager::AttributeSelected(TypeChange, NULL);
09319     AttributeManager::AttributeSelected(NULL, TypeChange);
09320 
09321 
09322 /*
09323     // And also change the line transparency type
09324     TypeChange = new AttrStrokeTranspTypeChange();
09325     if (TypeChange == NULL)
09326     {
09327         InformError();
09328         return;
09329     }
09330 
09331     TypeChange->SetTranspType(GetTranspType());
09332 
09333     AttributeManager::AttributeSelected(NULL, TypeChange);
09334 */
09335 }
09336 
09337 
09338 /********************************************************************************************
09339 
09340 >   void TranspInfoBarOp::ChangeDPI()
09341 
09342     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
09343     Created:    3/11/94
09344     Purpose:    Called when the dpi of a bitmap is changed by the user.
09345 
09346 ********************************************************************************************/
09347 
09348 void TranspInfoBarOp::ChangeDPI()
09349 {
09350     BOOL Valid;
09351     String_256 Str = GetStringGadgetValue(_R(IDC_SELPOINT), &Valid);
09352 
09353     if (Valid)
09354     {
09355         TRACEUSER( "Will", _T("String = %s\n"),(TCHAR*)Str);
09356 
09357         INT32 Length = Str.Length();
09358         TCHAR* StrText = (TCHAR*)Str;
09359 
09360         INT32 FirstNum = -1;
09361         INT32 Count = 0;
09362 
09363         for (INT32 i = 0; i < Length; ++i)
09364         {
09365             TCHAR chr = StrText[i];
09366             if (FirstNum == -1 && StringBase::IsNumeric(chr))
09367                 FirstNum = i;
09368 
09369             if (FirstNum != -1)
09370             {
09371                 if (StringBase::IsNumeric(chr))
09372                     Count++;
09373                 else
09374                     break;
09375             }
09376         }
09377 
09378         String_256 DpiStr;
09379         INT32 Dpi;
09380 
09381         if (FirstNum != -1 && Count > 0)
09382         {
09383             Str.Mid(&DpiStr, FirstNum, Count);
09384             Convert::StringToLong(DpiStr, &Dpi);
09385             TRACEUSER( "Will", _T("Dpi = %d\n"),Dpi);
09386 
09387             if (Dpi == 0)
09388                 Dpi = 1;
09389 
09390             AttrValueChange* NewDpi = new AttrBitmapDpiChange;
09391             if (NewDpi == NULL)
09392             {
09393                 InformError();
09394                 return;
09395             }
09396 
09397             NewDpi->MutateTranspFills(TRUE);
09398             ((AttrBitmapDpiChange*)NewDpi)->SetDPI(Dpi);
09399 
09400             AttributeManager::AttributeSelected(NULL, NewDpi);
09401         }
09402         else
09403         {
09404             TRACEUSER( "Will", _T("That was rubbish\n"));
09405             ShowCommonBitmapDpi();
09406         }
09407     }
09408     else
09409         TRACEUSER( "Will", _T("String was invalid\n"));
09410 }
09411 
09412 /********************************************************************************************
09413 
09414 >   void TranspInfoBarOp::ChangeTransparencyValue()
09415 
09416     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
09417     Created:    20/12/99
09418     Purpose:    Called when the transparency value is changed by the user.
09419 
09420 ********************************************************************************************/
09421 
09422 void TranspInfoBarOp::ChangeTransparencyValue()
09423 {
09424     BOOL Valid;
09425     String_256 Str = GetStringGadgetValue(_R(IDC_SELCOLOUR), &Valid);
09426 
09427     if (Valid)
09428     {
09429         INT32 Length = Str.Length();
09430         TCHAR* StrText = (TCHAR*)Str;
09431 
09432         INT32 FirstNum = -1;
09433         INT32 Count = 0;
09434 
09435         BOOL FoundDp = FALSE;
09436 
09437         for (INT32 i = 0; i < Length; ++i)
09438         {
09439             TCHAR chr = StrText[i];
09440             if (FirstNum == -1 && StringBase::IsNumeric(chr))
09441                 FirstNum = i;
09442 
09443             if (FirstNum != -1)
09444             {
09445                 if (StringBase::IsNumeric(chr))
09446                 {
09447                     Count++;
09448                     
09449                     //if (FoundDp == TRUE) { break; }
09450                 }
09451                 else if ((chr == '.') && (FoundDp == FALSE))
09452                 {
09453                     FoundDp = TRUE;
09454                     Count++;
09455                 }
09456                 else
09457                     break;
09458             }
09459         }
09460 
09461         String_256 TranspValStr;
09462         double TranspVal;
09463 
09464         if (FirstNum != -1 && Count > 0)
09465         {
09466             Str.Mid(&TranspValStr, FirstNum, Count);
09467             Convert::StringToDouble(TranspValStr, &TranspVal);
09468             
09469             // check for out of range stuff ....
09470 
09471             if (TranspVal < 0.0) { TranspVal = 0.0; }
09472             if (TranspVal > 100.0) { TranspVal = 100.0; }
09473             
09474             // convert data ....
09475 
09476             UINT32 Rounded = (UINT32) TranspVal;
09477             double Diff = TranspVal - Rounded;
09478 
09479             if (Diff < 0.5)
09480             {
09481                 if (Diff < 0.25) { TranspVal = (double) Rounded; }
09482                 else { TranspVal = (double) Rounded + 0.5; }
09483             }
09484             else
09485             {
09486                 if (Diff < 0.75) { TranspVal = (double) Rounded + 0.5; }
09487                 else { TranspVal = (double) ++Rounded; }
09488             }
09489 
09490             double AccurateNewVal = ((TranspVal * (double) SliderMax) / 100.0) + 0.5;
09491 
09492             SetTranspValue (static_cast<UINT32>(AccurateNewVal));
09493         }
09494         else
09495         {
09496             ShowControlPointInfo ();
09497         }
09498     }
09499 }
09500 
09501 /********************************************************************************************
09502 
09503 >   void TranspInfoBarOp::ChangeFractalGrain()
09504 
09505     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
09506     Created:    11/11/94
09507     Purpose:    Called when the Graininess of a fractal is changed by the user.
09508 
09509 ********************************************************************************************/
09510 
09511 void TranspInfoBarOp::ChangeFractalGrain (BOOL useEditbox /*= FALSE*/)
09512 {
09513     if (!useEditbox)
09514     {
09515         BOOL Valid;
09516         INT32 Result = GetLongGadgetValue(_R(IDC_TRANSPSLIDE), 0, SliderMax, 0, &Valid);
09517 
09518         if (Valid)
09519         {
09520             double Grain = GetDoubleGrain(Result);  
09521 
09522             TRACEUSER( "Will", _T("Graininess = %f\n"),Grain);
09523 
09524             if (Grain < 0.1)
09525                 Grain = 0.1;
09526 
09527             if (Grain > 16384)
09528                 Grain = 16384;
09529 
09530             AttrValueChange* NewGrain = new AttrFractalGrainChange;
09531             if (NewGrain == NULL)
09532             {
09533                 InformError();
09534                 return;
09535             }
09536             
09537             NewGrain->MutateTranspFills(TRUE);
09538             ((FractalFillAttribute*)NewGrain->GetAttributeValue())->Graininess = FIXED16(Grain);
09539 
09540             AttributeManager::AttributeSelected(NULL, NewGrain);
09541         }
09542     }
09543     else
09544     {
09545         BOOL Valid;
09546         String_256 Str = GetStringGadgetValue(_R(IDC_SELCOLOUR), &Valid);
09547 
09548         if (Valid)
09549         {
09550             INT32 Length = Str.Length();
09551             TCHAR* StrText = (TCHAR*)Str;
09552 
09553             INT32 FirstNum = -1;
09554             INT32 Count = 0;
09555 
09556             BOOL FoundDp = FALSE;
09557 
09558             for (INT32 i = 0; i < Length; ++i)
09559             {
09560                 TCHAR chr = StrText[i];
09561                 if (FirstNum == -1 && StringBase::IsNumeric(chr))
09562                     FirstNum = i;
09563 
09564                 if (FirstNum != -1)
09565                 {
09566                     if (StringBase::IsNumeric(chr))
09567                     {
09568                         Count++;
09569                         
09570                         //if (FoundDp == TRUE) { break; }
09571                     }
09572                     else if ((chr == '.') && (FoundDp == FALSE))
09573                     {
09574                         FoundDp = TRUE;
09575                         Count++;
09576                     }
09577                     else
09578                         break;
09579                 }
09580             }
09581 
09582             String_256 TranspValStr;
09583             double TranspVal;
09584 
09585             if (FirstNum != -1 && Count > 0)
09586             {
09587                 Str.Mid(&TranspValStr, FirstNum, Count);
09588                 Convert::StringToDouble(TranspValStr, &TranspVal);
09589                 
09590                 // check for out of range stuff ....
09591 
09592                 if (TranspVal < 0.0) { TranspVal = 0.0; }
09593                 if (TranspVal > 128.0) { TranspVal = 128.0; }
09594                 
09595                 // convert data ....
09596 
09597                 UINT32 Rounded = (UINT32) TranspVal;
09598                 double Diff = TranspVal - Rounded;
09599 
09600                 if (Diff < 0.5)
09601                 {
09602                     if (Diff < 0.25) { TranspVal = (double) Rounded; }
09603                     else { TranspVal = (double) Rounded + 0.5; }
09604                 }
09605                 else
09606                 {
09607                     if (Diff < 0.75) { TranspVal = (double) Rounded + 0.5; }
09608                     else { TranspVal = (double) ++Rounded; }
09609                 }
09610 
09611                 //double AccurateNewVal = ((TranspVal * (double) 128) / 128.0) + 0.5;
09612                 //double AccurateNewVal = TranspVal; //+ 0.5;
09613 
09614                 //UINT32 newVal = static_cast<UINT32>(AccurateNewVal);
09615 
09616                 AttrValueChange* NewGrain = new AttrFractalGrainChange;
09617                 if (NewGrain == NULL)
09618                 {
09619                     InformError();
09620                     return;
09621                 }
09622                 
09623                 NewGrain->MutateTranspFills(TRUE);
09624                 ((FractalFillAttribute*)NewGrain->GetAttributeValue())->Graininess = FIXED16(/*(INT32)*/ TranspVal);
09625 
09626                 AttributeManager::AttributeSelected(NULL, NewGrain);
09627             }
09628             else
09629             {
09630                 ShowFractalInfo ();
09631             }       
09632         }
09633     }
09634 }
09635 
09636 /********************************************************************************************
09637 
09638 >   void TranspInfoBarOp::ChangeNoiseScale()
09639 
09640     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
09641     Created:    11/11/94
09642     Purpose:    Called when the scale of a transparency is changed by the user.
09643 
09644 ********************************************************************************************/
09645 
09646 void TranspInfoBarOp::ChangeNoiseScale (BOOL useEditbox /*= FALSE*/)
09647 {
09648     if (!useEditbox)
09649     {
09650         BOOL Valid;
09651         INT32 Result = GetLongGadgetValue(_R(IDC_TRANSPSLIDE), 0, SliderMax, 0, &Valid);
09652 
09653         if (Valid)
09654         {
09655             double Scale = GetDoubleScale(Result);
09656 
09657             TRACEUSER( "Mike", _T("Scale = %f\n"),Scale);
09658 
09659             if (Scale < 0)
09660                 Scale = 0;
09661 
09662             if (Scale > 100)
09663                 Scale = 100;
09664 
09665             AttrValueChange* NewScale = new AttrNoiseScaleChange;
09666             if (NewScale == NULL)
09667             {
09668                 InformError();
09669                 return;
09670             }
09671             
09672             FIXED16 Grain = FIXED16(Scale);
09673             NewScale->MutateTranspFills(TRUE);
09674             ((NoiseFillAttribute*)NewScale->GetAttributeValue())->SetGraininess(Grain);
09675 
09676             AttributeManager::AttributeSelected(NULL, NewScale);
09677         }
09678     }
09679     else
09680     {
09681         BOOL Valid;
09682         String_256 Str = GetStringGadgetValue(_R(IDC_SELCOLOUR), &Valid);
09683 
09684         if (Valid)
09685         {
09686             INT32 Length = Str.Length();
09687             TCHAR* StrText = (TCHAR*)Str;
09688 
09689             INT32 FirstNum = -1;
09690             INT32 Count = 0;
09691 
09692             BOOL FoundDp = FALSE;
09693 
09694             for (INT32 i = 0; i < Length; ++i)
09695             {
09696                 TCHAR chr = StrText[i];
09697                 if (FirstNum == -1 && StringBase::IsNumeric(chr))
09698                     FirstNum = i;
09699 
09700                 if (FirstNum != -1)
09701                 {
09702                     if (StringBase::IsNumeric(chr))
09703                     {
09704                         Count++;
09705                         
09706                         //if (FoundDp == TRUE) { break; }
09707                     }
09708                     else if ((chr == '.') && (FoundDp == FALSE))
09709                     {
09710                         FoundDp = TRUE;
09711                         Count++;
09712                     }
09713                     else
09714                         break;
09715                 }
09716             }
09717 
09718             String_256 TranspValStr;
09719             double TranspVal;
09720 
09721             if (FirstNum != -1 && Count > 0)
09722             {
09723                 Str.Mid(&TranspValStr, FirstNum, Count);
09724                 Convert::StringToDouble(TranspValStr, &TranspVal);
09725                 
09726                 // check for out of range stuff ....
09727 
09728                 if (TranspVal < 0.0) { TranspVal = 0.0; }
09729                 if (TranspVal > 100.0) { TranspVal = 100.0; }
09730                 
09731                 // convert data ....
09732 
09733                 UINT32 Rounded = (UINT32) TranspVal;
09734                 double Diff = TranspVal - Rounded;
09735 
09736                 if (Diff < 0.5)
09737                 {
09738                     if (Diff < 0.25) { TranspVal = (double) Rounded; }
09739                     else { TranspVal = (double) Rounded + 0.5; }
09740                 }
09741                 else
09742                 {
09743                     if (Diff < 0.75) { TranspVal = (double) Rounded + 0.5; }
09744                     else { TranspVal = (double) ++Rounded; }
09745                 }
09746 
09747                 double AccurateNewVal = ((TranspVal * (double) SliderMax) / 100.0) + 0.5;
09748 
09749                 UINT32 newVal = static_cast<UINT32>(AccurateNewVal);
09750                 
09751                 //  SetTranspValue (static_cast<UINT32>(AccurateNewVal));
09752 
09753                 AttrValueChange* NewScale = new AttrNoiseScaleChange;
09754                 if (NewScale == NULL)
09755                 {
09756                     InformError();
09757                     return;
09758                 }
09759                 
09760                 FIXED16 Grain = FIXED16((INT32) newVal);
09761                 NewScale->MutateTranspFills(TRUE);
09762                 ((NoiseFillAttribute*)NewScale->GetAttributeValue())->SetGraininess(Grain);
09763 
09764                 AttributeManager::AttributeSelected(NULL, NewScale);
09765             }
09766             else
09767             {
09768                 ShowNoiseInfo ();
09769             }       
09770         }
09771     }
09772 }
09773 
09774 /********************************************************************************************
09775 
09776 >   AttrFillGeometry* TranspInfoBarOp::MakeFillMutator()
09777 
09778     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
09779     Created:    10/8/94
09780     Purpose:    Make a fill that will be used to Mutate another fill, changing it's type 
09781                 while retaining it's existing points and colours.
09782                 The fill type returned depends on the fill type menu state.
09783 
09784 ********************************************************************************************/
09785 
09786 AttrFillGeometry* TranspInfoBarOp::MakeFillMutator()
09787 {
09788     AttrFillGeometry* Fill = NULL;
09789     KernelBitmap* Default;
09790 
09791     switch (CurrentGeometryIndex)
09792     {
09793         case (FGMENU_FLATTRANSP):
09794             Fill = new AttrFlatTranspFill;
09795             break;
09796 
09797         case (FGMENU_LINEARTRANSP):
09798             Fill = new AttrLinearTranspFill;
09799             break;
09800 
09801         case (FGMENU_RADIALTRANSP):
09802             Fill = new AttrRadialTranspFill;
09803             if (Fill != NULL)
09804                 ((AttrRadialFill*)Fill)->MakeElliptical();
09805             break;
09806 
09807         case (FGMENU_CIRCULARTRANSP):
09808             Fill = new AttrRadialTranspFill;
09809             if (Fill != NULL)
09810                 ((AttrRadialFill*)Fill)->MakeCircular();
09811             break;
09812 
09813         case (FGMENU_CONICALTRANSP):
09814             Fill = new AttrConicalTranspFill;
09815             break;
09816 
09817         case (FGMENU_SQUARETRANSP):
09818             Fill = new AttrSquareTranspFill;
09819             break;
09820 
09821         case (FGMENU_THREECOLTRANSP):
09822             Fill = new AttrThreeColTranspFill;
09823             CloseProfileDialog (m_BiasGainGadget);      // cause fill type cannot be profiled!
09824             break;
09825 
09826         case (FGMENU_FOURCOLTRANSP):
09827             Fill = new AttrFourColTranspFill;
09828             CloseProfileDialog (m_BiasGainGadget);      // cause fill type cannot be profiled!
09829             break;
09830 
09831         case (FGMENU_BITMAPTRANSP):
09832             Fill = new AttrBitmapTranspFill;
09833 
09834             Default = KernelBitmap::MakeKernelBitmap();
09835             if (Default == NULL)
09836             {
09837                 delete Fill;
09838                 return NULL;
09839             }
09840 
09841             Fill->AttachBitmap(Default);
09842             break;
09843 
09844         case (FGMENU_FRACTALTRANSP):
09845             Fill = new AttrFractalTranspFill;
09846             break;
09847 
09848         case (FGMENU_NOISETRANSP):
09849             Fill = new AttrNoiseTranspFill;
09850             break;
09851 
09852         default:
09853             // Er .. Dunno what kind of fill this is ?
09854             Fill = new AttrFlatTranspFill;
09855             break;
09856     }
09857 
09858     return Fill;
09859 }
09860 
09861 /********************************************************************************************
09862 
09863 >   AttrFillGeometry* TranspInfoBarOp::GetCurrentGeometry()
09864 
09865     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
09866     Created:    10/8/94
09867     Purpose:    Gets the current Fill Geometry from the Attribute manager.
09868 
09869 ********************************************************************************************/
09870 
09871 AttrFillGeometry* TranspInfoBarOp::GetCurrentGeometry()
09872 {
09873     CCRuntimeClass* CurrentAttribGroup = 
09874         Tool::GetCurrent()->Parent->m_ToolInfo.CurrentAttributeGroup;
09875 
09876     Document* CurrentDoc = Document::GetSelected();
09877 
09878     if (CurrentDoc == NULL)
09879         return NULL; // We are not going to be able to do anything if there is no document
09880 
09881     return (AttrFillGeometry*)CurrentDoc->GetAttributeMgr()
09882                                 .GetCurrentAttribute(CurrentAttribGroup, 
09883                                             CC_RUNTIME_CLASS(AttrTranspFillGeometry));
09884 }
09885 
09886 /********************************************************************************************
09887 
09888 >   AttrPaintingMode* GradInfoBarOp::GetCurrentPaintingMode ()
09889 
09890     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
09891     Created:    2/12/99
09892     Purpose:    Gets the current painting mode from the Attribute manager.
09893 
09894 ********************************************************************************************/
09895 
09896 /*AttrPaintingMode* TranspInfoBarOp::GetCurrentPaintingMode ()
09897 {
09898     CCRuntimeClass* CurrentAttribGroup = 
09899         Tool::GetCurrent()->Parent->ToolInfo.CurrentAttributeGroup;
09900 
09901     Document* CurrentDoc = Document::GetSelected();
09902 
09903     if (CurrentDoc == NULL)
09904         return NULL; // We are not going to be able to do anything if there is no document
09905 
09906     return (AttrPaintingMode*)CurrentDoc->GetAttributeMgr()
09907                                 .GetCurrentAttribute(CurrentAttribGroup, 
09908                                             CC_RUNTIME_CLASS(AttrPaintingMode));
09909 }*/
09910 
09911 
09912 /********************************************************************************************
09913 
09914 >   AttrTranspFillMapping* TranspInfoBarOp::GetCurrentMapping()
09915 
09916     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
09917     Created:    10/8/94
09918     Purpose:    Gets the current Fill Geometry from the Attribute manager.
09919 
09920 ********************************************************************************************/
09921 
09922 AttrTranspFillMapping* TranspInfoBarOp::GetCurrentMapping()
09923 {
09924     CCRuntimeClass* CurrentAttribGroup = 
09925         Tool::GetCurrent()->Parent->m_ToolInfo.CurrentAttributeGroup;
09926 
09927     Document* CurrentDoc = Document::GetSelected();
09928 
09929     if (CurrentDoc == NULL)
09930         return NULL; // We are not going to be able to do anything if there is no document
09931 
09932     return (AttrTranspFillMapping*)CurrentDoc->GetAttributeMgr()
09933                                 .GetCurrentAttribute(CurrentAttribGroup, 
09934                                             CC_RUNTIME_CLASS(AttrTranspFillMapping));
09935 }
09936 
09937 double GetDoubleGrain(INT32 Pos)
09938 {
09939     return ( 128.0 * double(Pos)/double(GetGrainPosMax()) );
09940 }
09941 
09942 INT32 GetGrainPos(double Grain)
09943 {
09944     return INT32(Grain * double(GetGrainPosMax()) / 128.0 );
09945 }
09946 
09947 INT32 GetGrainPosMax()
09948 {
09949     return (1<<16);
09950 }
09951 
09952 double GetDoubleScale(INT32 Pos)
09953 {
09954     return ( 100.0 * double(Pos)/double(GetScalePosMax()) );
09955 }
09956 
09957 INT32 GetScalePos(double Scale)
09958 {
09959     return INT32(Scale * double(GetScalePosMax()) / 100.0 );
09960 }
09961 
09962 INT32 GetScalePosMax()
09963 {
09964     return (100);
09965 }
09966 
09967 
09968 
09969 
09970 /********************************************************************************************
09971 
09972 >   AttrFillGeometry* AttrRemoveTransp::MutateFill(AttrFillGeometry* FillToMutate) 
09973 
09974     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> (modified by Chris Snook)
09975     Created:    1/4/94
09976     Inputs:     The fill that is to be changed.
09977     Purpose:    Removes all transparency from a fill.
09978 
09979 ********************************************************************************************/
09980 
09981 AttrFillGeometry* AttrRemoveTransp::MutateFill(AttrFillGeometry* FillToMutate) 
09982 { 
09983     AttrFillGeometry* NewFill = new AttrFlatTranspFill;
09984     if (NewFill == NULL)
09985         return NULL;
09986 
09987     UINT32 TypeNone = TT_Mix;
09988     UINT32 NoTransp = 0;
09989 
09990     NewFill->SetTranspType(TypeNone);
09991     NewFill->SetStartTransp(&NoTransp);
09992 
09993     if (GetApplication()->GetBlobManager()->GetCurrentInterest().Fill && 
09994         FillToMutate->IsVisible() &&
09995         FillToMutate->FindParent() &&
09996         FillToMutate->FindParent()->IsSelected())
09997     {
09998         FillToMutate->RenderFillBlobs();
09999     }
10000 
10001     // Return the Mutated Fill
10002     return NewFill;
10003 }
10004 
10005 /********************************************************************************************
10006 
10007 >   virtual NodeAttribute* AttrRemoveTransp::GetOtherAttrToApply(BOOL* IsMutate)
10008 
10009     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
10010     Created:    17/8/95
10011     Returns:    The secondary attribute to apply, or NULL if none to apply
10012     Purpose:    Some attributes require a secondary atribute to be changed when they are
10013                 changed.  This routine obtains a pointer to the secondary attribute to
10014                 apply.
10015 
10016 ********************************************************************************************/
10017 
10018 NodeAttribute* AttrRemoveTransp::GetOtherAttrToApply(BOOL* IsMutate)
10019 {
10020     ERROR3IF(IsMutate == NULL, "NULL flag pointer passed to GetOtherAttrToApply");
10021 
10022     // Remove Transparency also need to remove line transparency
10023     NodeAttribute* OtherAttr = new AttrRemoveStrokeTransp;
10024     if (OtherAttr == NULL)
10025         return NULL;
10026 
10027     *IsMutate = TRUE;
10028 
10029     return OtherAttr;
10030 }
10031 
10032 /********************************************************************************************
10033 
10034 >   AttrFillGeometry* AttrRemoveStrokeTransp::MutateFill(AttrFillGeometry* FillToMutate) 
10035 
10036     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
10037     Created:    1/4/94
10038     Inputs:     The fill that is to be changed.
10039     Purpose:    Removes all transparency from a fill.
10040 
10041 ********************************************************************************************/
10042 
10043 AttrFillGeometry* AttrRemoveStrokeTransp::MutateFill(AttrFillGeometry* FillToMutate) 
10044 { 
10045     AttrFillGeometry* NewFill = new AttrStrokeTransp;
10046     if (NewFill == NULL)
10047         return NULL;
10048 
10049     UINT32 TypeNone = TT_Mix;
10050     UINT32 NoTransp = 0;
10051 
10052     NewFill->SetTranspType(TypeNone);
10053     NewFill->SetStartTransp(&NoTransp);
10054 
10055     // Return the Mutated Fill
10056     return NewFill;
10057 }
10058 
10059 /********************************************************************************************
10060 
10061 >   AttrFillGeometry* AttrMakeFlatTransp::MutateFill(AttrFillGeometry* FillToMutate) 
10062 
10063     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
10064     Created:    1/4/94
10065     Inputs:     The fill that is to be changed.
10066     Purpose:    Forces a 50% flat transparency.
10067 
10068 ********************************************************************************************/
10069 
10070 AttrFillGeometry* AttrMakeFlatTransp::MutateFill(AttrFillGeometry* FillToMutate) 
10071 { 
10072     AttrFillGeometry* NewFill = new AttrFlatTranspFill;
10073     if (NewFill == NULL)
10074         return NULL;
10075 
10076     UINT32 Transp = *FillToMutate->GetStartTransp();
10077 
10078     if (FillToMutate->GetTranspType() == TT_Mix &&
10079         *FillToMutate->GetStartTransp() == 0)
10080     {
10081         Transp = 128;
10082     }
10083 
10084     NewFill->SetTranspType(FillToMutate->GetTranspType());
10085     NewFill->SetStartTransp(&Transp);
10086 
10087     // WEBSTER-Martin-02/12/96
10088 //#ifdef WEBSTER
10089     // Make sure a FlatTransparency can change its value bearing in mind the user can't
10090     // change the blob selection
10091 //  NewFill->SelectBlob(FILLCONTROL_STARTPOINT);
10092     //NewFill->SetBlobState(FILLCONTROL_STARTPOINT, TRUE);
10093     //AttrFillGeometry::SelectionCount = AttrFillGeometry::CountSelectionControlPoints();
10094 //#endif //WEBSTER
10095 
10096     if (GetApplication()->GetBlobManager()->GetCurrentInterest().Fill && 
10097         FillToMutate->IsVisible() &&
10098         FillToMutate->FindParent() &&
10099         FillToMutate->FindParent()->IsSelected())
10100     {
10101         FillToMutate->RenderFillBlobs();
10102     }
10103 
10104     // Return the Mutated Fill
10105     return NewFill;
10106 }
10107 
10108 /********************************************************************************************
10109 
10110 >   virtual NodeAttribute* AttrMakeFlatTransp::GetOtherAttrToApply(BOOL* IsMutate)
10111 
10112     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
10113     Created:    17/8/95
10114     Returns:    The secondary attribute to apply, or NULL if none to apply
10115     Purpose:    Some attributes require a secondary atribute to be changed when they are
10116                 changed.  This routine obtains a pointer to the secondary attribute to
10117                 apply.
10118 
10119 ********************************************************************************************/
10120 
10121 NodeAttribute* AttrMakeFlatTransp::GetOtherAttrToApply(BOOL* IsMutate)
10122 {
10123     ERROR3IF(IsMutate == NULL, "NULL flag pointer passed to GetOtherAttrToApply");
10124 
10125     // A transparency change also needs to set the Stroke Transparency
10126     NodeAttribute* OtherAttr = new AttrStrokeTranspChange;
10127     if (OtherAttr == NULL)
10128         return NULL;
10129 
10130     UINT32 Transp = 128;
10131 
10132     ((AttrStrokeTranspChange *)OtherAttr)->SetStartTransp(&Transp);
10133 
10134     *IsMutate = TRUE;
10135 
10136     return OtherAttr;
10137 }
10138 
10139 
10140 
10143 
10144 //          Implementation of class OpChangeFillProfile
10145 
10148 
10149 
10150 
10151 /********************************************************************************************
10152 
10153 >   OpChangeFillProfile::OpChangeFillProfile()
10154 
10155     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
10156     Created:    7/2/2000
10157     Inputs:     -
10158     Purpose:    Construct an object of this type.
10159 
10160 ********************************************************************************************/
10161 
10162 OpChangeFillProfile::OpChangeFillProfile()
10163 {
10164 }
10165 
10166 
10167 
10168 /********************************************************************************************
10169 
10170 >   OpChangeFillProfile::~OpChangeFillProfile()
10171 
10172     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
10173     Created:    7/2/2000
10174     Inputs:     -
10175     Purpose:    Destruct an object of this type.
10176 
10177 ********************************************************************************************/
10178 
10179 OpChangeFillProfile::~OpChangeFillProfile()
10180 {
10181 }
10182 
10183 
10184 
10185 /********************************************************************************************
10186 
10187 >   BOOL OpChangeFillProfile::Declare()
10188 
10189     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
10190     Created:    7/2/2000
10191     Returns:    TRUE if all went OK, False otherwise
10192     Purpose:    Adds the operation to the list of all known operations.
10193 
10194 ********************************************************************************************/
10195 
10196 BOOL OpChangeFillProfile::Declare()
10197 {
10198     return (RegisterOpDescriptor(
10199                                 0, 
10200                                 _R(IDS_FILLPROFILE),
10201                                 CC_RUNTIME_CLASS(OpChangeFillProfile), 
10202                                 OPTOKEN_FILLPROFILE,
10203                                 OpChangeFillProfile::GetState));
10204 }
10205 
10206 
10207 
10208 /********************************************************************************************
10209 
10210 >   void OpChangeFillProfile::DoWithParam(OpDescriptor* pOp, OpParam* pParam)
10211 
10212     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
10213     Created:    7/2/2000
10214     Returns:    -
10215     Purpose:    Saves the fill profile at this point, so it can be restored on an undo.
10216 
10217 ********************************************************************************************/
10218 
10219 void OpChangeFillProfile::DoWithParam(OpDescriptor* pOp, OpParam* pParam)
10220 {
10221     // Start a slow job
10222     //BeginSlowJob();
10223     DoStartSelOp(TRUE);
10224 
10225     // run through the selection changing all profiles
10226     CProfileBiasGain Profile;
10227 
10228     // recast the op param
10229     FillProfileOpParam * pProfileParam = (FillProfileOpParam *)pParam;
10230 
10231     List ShadowList;
10232 // Why does this change ALL profiles - even those deep down in the selection???
10233 //  FillTools::BuildListOfSelectedNodes(&ShadowList, CC_RUNTIME_CLASS(AttrFillGeometry));
10234     FillTools::GetSelectedAttrList(&ShadowList, CC_RUNTIME_CLASS(AttrFillGeometry), TRUE, FALSE);
10235 
10236     NodeListItem * pItem = (NodeListItem *)ShadowList.GetHead();
10237 
10238     CProfileBiasGain OldGain;
10239 
10240     while (pItem)
10241     {
10242         if (pItem->pNode)
10243         {
10244             // initialise the action
10245             ChangeFillProfileAction * pAction;
10246 
10247             ChangeFillProfileAction::Init(this, GetUndoActionList(), (AttrFillGeometry *)pItem->pNode, pProfileParam->Profile,
10248                 &pAction);
10249 
10250             // Inform the effected parents of the change
10251 
10252             ObjChangeFlags cFlags;
10253             cFlags.Attribute = TRUE;        // Needed to make Blends re-calc themselves
10254 
10255             ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,NULL);
10256 
10257             /*(AttrFillGeometry *)*/ (pItem->pNode)->AllowOp(&ObjChange);
10258 
10259             ObjChange.Define(OBJCHANGE_FINISHED,cFlags,NULL,NULL);
10260             UpdateAllChangedNodes(&ObjChange);
10261         }
10262 
10263         pItem = (NodeListItem *)ShadowList.GetNext(pItem);
10264     }
10265 
10266     ShadowList.DeleteAll();
10267 
10268     End();
10269 }
10270 
10271 
10272 
10273 /********************************************************************************************
10274 
10275 >   OpState OpChangeFillProfile::GetState(String_256* Description, OpDescriptor*)
10276 
10277     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
10278     Created:    7/2/2000
10279     Returns:    Ungreyed, Unticked
10280     Purpose:    Determines the state of the op.
10281 
10282 ********************************************************************************************/
10283 
10284 OpState OpChangeFillProfile::GetState(String_256* Description, OpDescriptor*)
10285 {
10286     OpState Blobby;
10287     
10288     return Blobby;
10289 }
10290 
10291 
10292 
10295 
10296 //          Implementation of class ChangeFillProfileAction
10297 
10300 
10301 
10302 
10303 /********************************************************************************************
10304 
10305 >   ChangeFillProfileAction::ChangeFillProfileAction()
10306 
10307     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
10308     Created:    7/2/2000
10309     Inputs:     -
10310     Purpose:    Construct an object of this type.
10311 
10312 ********************************************************************************************/
10313 
10314 ChangeFillProfileAction::ChangeFillProfileAction()
10315 {
10316     m_pNodeFill = NULL;
10317 }
10318 
10319 
10320 
10321 /********************************************************************************************
10322 
10323 >   ChangeFillProfileAction::~ChangeFillProfileAction()
10324 
10325     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
10326     Created:    7/2/2000
10327     Inputs:     -
10328     Purpose:    Destruct an object of this type.
10329 
10330 ********************************************************************************************/
10331 
10332 ChangeFillProfileAction::~ChangeFillProfileAction()
10333 {
10334 }
10335 
10336 
10337 
10338 /********************************************************************************************
10339 
10340 >   ActionCode ChangeFillProfileAction::Init(Operation* pOp,
10341                                         ActionList* pActionList,
10342                                         AttrFillGeometry* pThisNodeFill,
10343                                         CProfileBiasGain &Profile,
10344                                         ChangeFillProfileAction** NewAction,
10345                                         BOOL bReverse = TRUE,
10346                                         BOOL bCache = FALSE)
10347 {
10348 
10349     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
10350     Created:    7/2/2000
10351     Inputs:     pOp             = ptr to the operation to which this action belongs
10352                 pActionList     = ptr to action list to which this action should be added
10353                 pThisNodeFill   = ptr to NodeFill to change 
10354                 Profile         = New profile to apply to pThisNodeFill
10355     Outputs:    ppNewAction     = ptr to a ptr to an action, allowing the function to return
10356                                   a pointer to the created action
10357     Returns:    ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL
10358     Purpose:    This is the function which creates an instance of this action. If there is no room 
10359                 in the undo buffer (which is determined by the base class Init function called within)
10360                 the function will either return AC_NO_RECORD which means the operation can continue, 
10361                 but no undo information needs to be stored, or AC_OK which means the operation should
10362                 continue AND record undo information. If the function returns AC_FAIL, there was not 
10363                 enough memory to record the undo information, and the user has decided not to continue
10364                 with the operation.
10365     Errors:     -
10366     SeeAlso:    Action::Init()
10367 
10368 ********************************************************************************************/
10369 
10370 ActionCode ChangeFillProfileAction::Init(Operation* pOp,
10371                                         ActionList* pActionList,
10372                                         AttrFillGeometry* pThisNodeFill,
10373                                         CProfileBiasGain &Profile,
10374                                         ChangeFillProfileAction** NewAction,
10375                                         BOOL bReverse /*= TRUE*/,
10376                                         BOOL bCache /*= FALSE*/)
10377 {
10378     UINT32 ActSize = sizeof(ChangeFillProfileAction);
10379 
10380     ActionCode Ac = Action::Init(pOp,pActionList,ActSize, CC_RUNTIME_CLASS(ChangeFillProfileAction), (Action**)NewAction);
10381 
10382     if (Ac != AC_FAIL)
10383     {
10384         Document * pDoc = Document::GetCurrent();
10385         
10386         // reverse the action
10387         if (bReverse)
10388         {
10389             pActionList->RemoveItem(*NewAction);
10390             pActionList->AddHead(*NewAction);
10391         }
10392         
10393         (*NewAction)->m_pNodeFill = pThisNodeFill;
10394         FillGeometryAttribute* temp =  (FillGeometryAttribute*) pThisNodeFill->GetAttributeValue ();
10395         (*NewAction)->m_LastProfile = temp->GetProfile ();
10396 
10397         NodeRenderableInk* pNode = (NodeRenderableInk*) pThisNodeFill->FindParent ();
10398 
10399         // set the values, invalidate and regenerate
10400 
10401         temp->SetProfile(Profile);
10402 
10403         pDoc->ForceRedraw(pThisNodeFill->FindParentSpread(), 
10404                           pNode->GetBoundingRect(), FALSE, pNode);
10405     }
10406 
10407     return Ac;
10408 }
10409 
10410 
10411 
10412 /********************************************************************************************
10413 
10414 >   void ChangeFillProfileAction::ChangeFillProfileWithNoUndo (Operation* pOp, CProfileBiasGain &Profile)
10415 
10416     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
10417     Created:    24/2/2000
10418     Inputs:     Profile - the profile that is to be applied directly (i.e.  applied with no undo)
10419     Purpose:    When applying fill profiles, we only want to generate one bit of undo information.
10420                 This function allows us to meet this requirement (the one bit of undo information
10421                 is generated via OpChangeFillProfile::DoWithParam ()).  This function is ONLY
10422                 called from within GradInfoBarOp::ChangeProfile () - after
10423                 OpChangeFillProfile::DoWithParam () has been called.
10424     Errors:     -
10425     SeeAlso:    GradInfoBarOp::ChangeProfile (), OpChangeFillProfile::DoWithParam ().
10426 
10427 ********************************************************************************************/
10428 
10429 void ChangeFillProfileAction::ChangeFillProfileWithNoUndo (CProfileBiasGain &Profile)
10430 {
10431     Document * pDoc = Document::GetCurrent();
10432 
10433     List ShadowList;
10434 // Why does this change ALL profiles - even those deep down in the selection???
10435 //  FillTools::BuildListOfSelectedNodes(&ShadowList, CC_RUNTIME_CLASS(AttrFillGeometry));
10436     FillTools::GetSelectedAttrList(&ShadowList, CC_RUNTIME_CLASS(AttrFillGeometry), TRUE, FALSE);
10437 
10438     NodeListItem * pItem = (NodeListItem *)ShadowList.GetHead();
10439 
10440     CProfileBiasGain OldGain;
10441 
10442     while (pItem)
10443     {
10444         if (pItem->pNode)
10445         {
10446             AttrFillGeometry* pThisNodeFill = (AttrFillGeometry *)pItem->pNode;
10447                     
10448             FillGeometryAttribute* temp =  (FillGeometryAttribute*) pThisNodeFill->GetAttributeValue ();
10449             temp->SetProfile(Profile);
10450 
10451             NodeRenderableInk* pNode = (NodeRenderableInk*) pThisNodeFill->FindParent ();
10452             Node* pParent = pNode->FindParent ();
10453 
10454             // decide the best option for causing a redraw
10455             
10456             if (IS_A(pParent, Layer))           // a simple node is selected
10457             {
10458                 pDoc->ForceRedraw(pThisNodeFill->FindParentSpread(), 
10459                                   pNode->GetBoundingRect(), FALSE, pNode);
10460             }
10461             else
10462             {
10463                 ObjChangeFlags cFlags;
10464                 cFlags.Attribute = TRUE;        // Needed to make Blends re-calc themselves
10465 
10466                 ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,NULL);
10467 
10468                 /*(AttrFillGeometry *)*/ (pItem->pNode)->AllowOp(&ObjChange);
10469 
10470                 ObjChange.Define(OBJCHANGE_FINISHED,cFlags,NULL,NULL);
10471                     
10472                 Operation TempOp;
10473 
10474                 TempOp.UpdateAllChangedNodes(&ObjChange);
10475             }
10476         }
10477 
10478         pItem = (NodeListItem *)ShadowList.GetNext(pItem);
10479     }
10480 
10481     ShadowList.DeleteAll();
10482 
10483     if (pDoc->GetOpHistory ().CanRedo ())
10484     {
10485         // then we need to clear out the redo information - since we are now 'before' it ....
10486         pDoc->GetOpHistory ().DeleteRedoableOps ();
10487 
10488         // and update the state of things ....
10489         DialogBarOp::SetSystemStateChanged();
10490         DialogBarOp::UpdateStateOfAllBars();
10491     }
10492 }
10493 
10494 
10495 
10496 /********************************************************************************************
10497 
10498 >   ActionCode ChangeFillProfileAction::Execute()
10499 
10500     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
10501     Created:    7/2/2000
10502     Inputs:     -
10503     Outputs:    -
10504     Returns:    ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL
10505     Purpose:    Executes the action.  This will reset the fill profile in
10506                 m_pNodeFill to its previous one, after creating another action to
10507                 record the current fill profile of m_pNodeFill in.
10508     Errors:     -
10509     SeeAlso:    Action::Init()
10510 
10511 ********************************************************************************************/
10512 
10513 ActionCode ChangeFillProfileAction::Execute()
10514 {
10515     ActionCode Act;
10516     ChangeFillProfileAction* pAction;
10517 
10518     Act = ChangeFillProfileAction::Init(    pOperation, 
10519                                             pOppositeActLst,
10520                                             m_pNodeFill,
10521                                             m_LastProfile,
10522                                             &pAction,
10523                                             TRUE,
10524                                             FALSE);
10525     
10526     return (Act);
10527 }
10528 
10529 
10530 
10533 
10534 //          Implementation of class OpChangeTranspFillProfile
10535 
10538 
10539 
10540 
10541 /********************************************************************************************
10542 
10543 >   OpChangeTranspFillProfile::OpChangeTranspFillProfile()
10544 
10545     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
10546     Created:    10/2/2000
10547     Inputs:     -
10548     Purpose:    Construct an object of this type.
10549 
10550 ********************************************************************************************/
10551 
10552 OpChangeTranspFillProfile::OpChangeTranspFillProfile()
10553 {
10554 }
10555 
10556 
10557 
10558 /********************************************************************************************
10559 
10560 >   OpChangeTranspFillProfile::~OpChangeTranspFillProfile()
10561 
10562     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
10563     Created:    10/2/2000
10564     Inputs:     -
10565     Purpose:    Destruct an object of this type.
10566 
10567 ********************************************************************************************/
10568 
10569 OpChangeTranspFillProfile::~OpChangeTranspFillProfile()
10570 {
10571 }
10572 
10573 
10574 
10575 /********************************************************************************************
10576 
10577 >   BOOL OpChangeTranspFillProfile::Declare()
10578 
10579     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
10580     Created:    10/2/2000
10581     Returns:    TRUE if all went OK, False otherwise
10582     Purpose:    Adds the operation to the list of all known operations.
10583 
10584 ********************************************************************************************/
10585 
10586 BOOL OpChangeTranspFillProfile::Declare()
10587 {
10588     return (RegisterOpDescriptor(
10589                                 0, 
10590                                 _R(IDS_TRANSPFILLPROFILE),
10591                                 CC_RUNTIME_CLASS(OpChangeTranspFillProfile), 
10592                                 OPTOKEN_TRANSPFILLPROFILE,
10593                                 OpChangeTranspFillProfile::GetState));
10594 }
10595 
10596 
10597 
10598 /********************************************************************************************
10599 
10600 >   void OpChangeTranspFillProfile::DoWithParam(OpDescriptor* pOp, OpParam* pParam)
10601 
10602     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
10603     Created:    10/2/2000
10604     Returns:    -
10605     Purpose:    Saves the transparency profile at this point, so it can be restored on
10606                 an undo.
10607 
10608 ********************************************************************************************/
10609 
10610 void OpChangeTranspFillProfile::DoWithParam(OpDescriptor* pOp, OpParam* pParam)
10611 {
10612     // Start a slow job
10613     //BeginSlowJob();
10614     DoStartSelOp(TRUE);
10615 
10616     // run through the selection changing all profiles
10617     CProfileBiasGain Profile;
10618 
10619     // recast the op param
10620     FillProfileOpParam * pProfileParam = (FillProfileOpParam *)pParam;
10621 
10622     List ShadowList;
10623 // Why does this change ALL profiles - even those deep down in the selection???
10624 //  FillTools::BuildListOfSelectedNodes(&ShadowList, CC_RUNTIME_CLASS(AttrTranspFillGeometry));
10625     FillTools::GetSelectedAttrList(&ShadowList, CC_RUNTIME_CLASS(AttrTranspFillGeometry), TRUE, TRUE);
10626 
10627     NodeListItem * pItem = (NodeListItem *)ShadowList.GetHead();
10628 
10629     CProfileBiasGain OldGain;
10630 
10631     while (pItem)
10632     {
10633         if (pItem->pNode)
10634         {
10635             // initialise the action
10636             ChangeFillProfileAction * pAction;
10637 
10638             ChangeFillProfileAction::Init(this, GetUndoActionList(), (AttrFillGeometry *)pItem->pNode, pProfileParam->Profile,
10639                 &pAction);
10640 
10641             // Inform the effected parents of the change
10642 
10643             ObjChangeFlags cFlags;
10644             cFlags.Attribute = TRUE;        // Needed to make Blends re-calc themselves
10645 
10646             ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,NULL);
10647 
10648             /*(AttrFillGeometry *)*/ (pItem->pNode)->AllowOp(&ObjChange);
10649 
10650             ObjChange.Define(OBJCHANGE_FINISHED,cFlags,NULL,NULL);
10651             UpdateAllChangedNodes(&ObjChange);
10652         }
10653 
10654         pItem = (NodeListItem *)ShadowList.GetNext(pItem);
10655     }
10656 
10657     ShadowList.DeleteAll();
10658 
10659     End();
10660 }
10661 
10662 
10663 
10664 /********************************************************************************************
10665 
10666 >   OpState OpChangeTranspFillProfile::GetState(String_256* Description, OpDescriptor*)
10667 
10668     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
10669     Created:    10/2/2000
10670     Returns:    Ungreyed, Unticked
10671     Purpose:    Determines the state of the op.
10672 
10673 ********************************************************************************************/
10674 
10675 OpState OpChangeTranspFillProfile::GetState(String_256* Description, OpDescriptor*)
10676 {
10677     OpState Blobby;
10678     
10679     return (Blobby);
10680 }
10681 
10682 
10683 
10686 
10687 //          Implementation of class ChangeTranspFillProfileAction
10688 
10691 
10692 
10693 
10694 /********************************************************************************************
10695 
10696 >   ChangeTranspFillProfileAction::ChangeTranspFillProfileAction()
10697 
10698     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
10699     Created:    10/2/2000
10700     Inputs:     -
10701     Purpose:    Construct an object of this type.
10702 
10703 ********************************************************************************************/
10704 
10705 ChangeTranspFillProfileAction::ChangeTranspFillProfileAction()
10706 {
10707     m_pNodeTranspFill = NULL;
10708 }
10709 
10710 
10711 
10712 /********************************************************************************************
10713 
10714 >   ChangeTranspFillProfileAction::~ChangeTranspFillProfileAction()
10715 
10716     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
10717     Created:    10/2/2000
10718     Inputs:     -
10719     Purpose:    Destruct an object of this type.
10720 
10721 ********************************************************************************************/
10722 
10723 ChangeTranspFillProfileAction::~ChangeTranspFillProfileAction()
10724 {
10725 }
10726 
10727 
10728 
10729 /********************************************************************************************
10730 
10731 >   ActionCode ChangeTranspFillProfileAction::Init(Operation* pOp,
10732                                                ActionList* pActionList,
10733                                                AttrFillGeometry* pThisNodeTranspFill,
10734                                                CProfileBiasGain &Profile,
10735                                                ChangeTranspFillProfileAction** NewAction,
10736                                                BOOL bReverse = TRUE,
10737                                                BOOL bCache = FALSE)
10738 
10739     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
10740     Created:    10/2/2000
10741     Inputs:     pOp             = ptr to the operation to which this action belongs
10742                 pActionList     = ptr to action list to which this action should be added
10743                 pThisNodeTranspFill = ptr to NodeTranspFill to change 
10744                 Profile         = New profile to apply to pThisNodeTranspFill
10745     Outputs:    ppNewAction     = ptr to a ptr to an action, allowing the function to return
10746                                   a pointer to the created action
10747     Returns:    ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL
10748     Purpose:    This is the function which creates an instance of this action. If there is no room 
10749                 in the undo buffer (which is determined by the base class Init function called within)
10750                 the function will either return AC_NO_RECORD which means the operation can continue, 
10751                 but no undo information needs to be stored, or AC_OK which means the operation should
10752                 continue AND record undo information. If the function returns AC_FAIL, there was not 
10753                 enough memory to record the undo information, and the user has decided not to continue
10754                 with the operation.
10755     Errors:     -
10756     SeeAlso:    Action::Init()
10757 
10758 ********************************************************************************************/
10759 
10760 ActionCode ChangeTranspFillProfileAction::Init(Operation* pOp,
10761                                                ActionList* pActionList,
10762                                                AttrFillGeometry* pThisNodeTranspFill,
10763                                                CProfileBiasGain &Profile,
10764                                                ChangeTranspFillProfileAction** NewAction,
10765                                                BOOL bReverse /*= TRUE*/,
10766                                                BOOL bCache /*= FALSE*/)
10767 {
10768     UINT32 ActSize = sizeof(ChangeTranspFillProfileAction);
10769 
10770     ActionCode Ac = Action::Init(pOp,pActionList,ActSize, CC_RUNTIME_CLASS(ChangeTranspFillProfileAction), (Action**)NewAction);
10771 
10772     if (Ac != AC_FAIL)
10773     {
10774         Document * pDoc = Document::GetCurrent();
10775         
10776         // reverse the action
10777         if (bReverse)
10778         {
10779             pActionList->RemoveItem(*NewAction);
10780             pActionList->AddHead(*NewAction);
10781         }
10782         
10783         (*NewAction)->m_pNodeTranspFill = pThisNodeTranspFill;
10784         FillGeometryAttribute* temp =  (FillGeometryAttribute*) pThisNodeTranspFill->GetAttributeValue ();
10785         (*NewAction)->m_LastProfile = temp->GetProfile ();
10786 
10787         NodeRenderableInk* pNode = (NodeRenderableInk*) pThisNodeTranspFill->FindParent ();
10788 
10789         // set the values, invalidate and regenerate
10790 
10791         temp->SetProfile(Profile);
10792 
10793         pDoc->ForceRedraw(pThisNodeTranspFill->FindParentSpread(), 
10794                 pNode->GetBoundingRect(), FALSE, pNode);
10795     }
10796 
10797     return Ac;
10798 }
10799 
10800 
10801 
10802 /********************************************************************************************
10803 
10804 >   void ChangeTranspFillProfileAction::ChangeTranspFillProfileWithNoUndo (CProfileBiasGain &Profile)
10805 
10806     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
10807     Created:    25/2/2000
10808     Inputs:     Profile - the profile that is to be applied directly (i.e.  applied with no undo)
10809     Purpose:    When applying transp fill profiles, we only want to generate one bit of undo information.
10810                 This function allows us to meet this requirement (the one bit of undo information
10811                 is generated via OpChangeTranspFillProfile::DoWithParam ()).  This function is ONLY
10812                 called from within TranspInfoBarOp::ChangeProfile () - after
10813                 OpChangeTranspFillProfile::DoWithParam () has been called.
10814     Errors:     -
10815     SeeAlso:    GradInfoBarOp::ChangeProfile (), OpChangeTranspFillProfile::DoWithParam ().
10816 
10817 ********************************************************************************************/
10818 
10819 void ChangeTranspFillProfileAction::ChangeTranspFillProfileWithNoUndo (CProfileBiasGain &Profile)
10820 {
10821     Document * pDoc = Document::GetCurrent();
10822 
10823     List ShadowList;
10824 // Why does this change ALL profiles - even those deep down in the selection???
10825 //  FillTools::BuildListOfSelectedNodes(&ShadowList, CC_RUNTIME_CLASS(AttrTranspFillGeometry));
10826     FillTools::GetSelectedAttrList(&ShadowList, CC_RUNTIME_CLASS(AttrTranspFillGeometry), TRUE, TRUE);
10827 
10828     NodeListItem * pItem = (NodeListItem *)ShadowList.GetHead();
10829 
10830     CProfileBiasGain OldGain;
10831 
10832     while (pItem)
10833     {
10834         if (pItem->pNode)
10835         {
10836             AttrFillGeometry* pThisNodeFill = (AttrFillGeometry *)pItem->pNode;
10837                     
10838             FillGeometryAttribute* temp =  (FillGeometryAttribute*) pThisNodeFill->GetAttributeValue ();
10839             temp->SetProfile(Profile);
10840 
10841             NodeRenderableInk* pNode = (NodeRenderableInk*) pThisNodeFill->FindParent ();
10842             Node* pParent = pNode->FindParent ();
10843 
10844             // decide the best option for causing a redraw
10845             
10846             if (IS_A(pParent, Layer))           // a simple node is selected
10847             {
10848                 pDoc->ForceRedraw(pThisNodeFill->FindParentSpread(),
10849                                   pNode->GetBoundingRect(), FALSE, pNode);
10850             }
10851             else
10852             {
10853                 ObjChangeFlags cFlags;
10854                 cFlags.Attribute = TRUE;        // Needed to make Blends re-calc themselves
10855 
10856                 ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,NULL);
10857 
10858                 /*(AttrFillGeometry *)*/ (pItem->pNode)->AllowOp(&ObjChange);
10859 
10860                 ObjChange.Define(OBJCHANGE_FINISHED,cFlags,NULL,NULL);
10861                     
10862                 Operation TempOp;
10863 
10864                 TempOp.UpdateAllChangedNodes(&ObjChange);
10865             }
10866         }
10867 
10868         pItem = (NodeListItem *)ShadowList.GetNext(pItem);
10869     }
10870 
10871     ShadowList.DeleteAll();
10872 
10873     if (pDoc->GetOpHistory ().CanRedo ())
10874     {
10875         // then we need to clear out the redo information - since we are now 'before' it ....
10876         pDoc->GetOpHistory ().DeleteRedoableOps ();
10877 
10878         // and update the state of things ....
10879         DialogBarOp::SetSystemStateChanged();
10880         DialogBarOp::UpdateStateOfAllBars();
10881     }
10882 }
10883 
10884 
10885 
10886 /********************************************************************************************
10887 
10888 >   ActionCode ChangeTranspFillProfileAction::Execute()
10889 
10890     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
10891     Created:    10/2/2000
10892     Inputs:     -
10893     Outputs:    -
10894     Returns:    ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL
10895     Purpose:    Executes the action.  This will reset the transparency profile in
10896                 m_pNodeTranspFill to its previous one, after creating another action to
10897                 record the current transparency profile of m_pNodeTranspFill in.
10898     Errors:     -
10899     SeeAlso:    Action::Init()
10900 
10901 ********************************************************************************************/
10902 
10903 ActionCode ChangeTranspFillProfileAction::Execute()
10904 {
10905     ActionCode Act;
10906     ChangeFillProfileAction* pAction;
10907 
10908     Act = ChangeFillProfileAction::Init(    pOperation, 
10909                                             pOppositeActLst,
10910                                             m_pNodeTranspFill,
10911                                             m_LastProfile,
10912                                             &pAction,
10913                                             TRUE,
10914                                             FALSE);
10915     
10916     return (Act);
10917 }

Generated on Sat Nov 10 03:47:37 2007 for Camelot by  doxygen 1.4.4