cartprov.cpp

Go to the documentation of this file.
00001 // $Id: cartprov.cpp 1013 2006-05-11 20:24:13Z alex $
00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE
00003 ================================XARAHEADERSTART===========================
00004  
00005                Xara LX, a vector drawing and manipulation program.
00006                     Copyright (C) 1993-2006 Xara Group Ltd.
00007        Copyright on certain contributions may be held in joint with their
00008               respective authors. See AUTHORS file for details.
00009 
00010 LICENSE TO USE AND MODIFY SOFTWARE
00011 ----------------------------------
00012 
00013 This file is part of Xara LX.
00014 
00015 Xara LX is free software; you can redistribute it and/or modify it
00016 under the terms of the GNU General Public License version 2 as published
00017 by the Free Software Foundation.
00018 
00019 Xara LX and its component source files are distributed in the hope
00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the
00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00022 See the GNU General Public License for more details.
00023 
00024 You should have received a copy of the GNU General Public License along
00025 with Xara LX (see the file GPL in the root directory of the
00026 distribution); if not, write to the Free Software Foundation, Inc., 51
00027 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
00028 
00029 
00030 ADDITIONAL RIGHTS
00031 -----------------
00032 
00033 Conditional upon your continuing compliance with the GNU General Public
00034 License described above, Xara Group Ltd grants to you certain additional
00035 rights. 
00036 
00037 The additional rights are to use, modify, and distribute the software
00038 together with the wxWidgets library, the wxXtra library, and the "CDraw"
00039 library and any other such library that any version of Xara LX relased
00040 by Xara Group Ltd requires in order to compile and execute, including
00041 the static linking of that library to XaraLX. In the case of the
00042 "CDraw" library, you may satisfy obligation under the GNU General Public
00043 License to provide source code by providing a binary copy of the library
00044 concerned and a copy of the license accompanying it.
00045 
00046 Nothing in this section restricts any of the rights you have under
00047 the GNU General Public License.
00048 
00049 
00050 SCOPE OF LICENSE
00051 ----------------
00052 
00053 This license applies to this program (XaraLX) and its constituent source
00054 files only, and does not necessarily apply to other Xara products which may
00055 in part share the same code base, and are subject to their own licensing
00056 terms.
00057 
00058 This license does not apply to files in the wxXtra directory, which
00059 are built into a separate library, and are subject to the wxWindows
00060 license contained within that directory in the file "WXXTRA-LICENSE".
00061 
00062 This license does not apply to the binary libraries (if any) within
00063 the "libs" directory, which are subject to a separate license contained
00064 within that directory in the file "LIBS-LICENSE".
00065 
00066 
00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS
00068 ----------------------------------------------
00069 
00070 Subject to the terms of the GNU Public License (see above), you are
00071 free to do whatever you like with your modifications. However, you may
00072 (at your option) wish contribute them to Xara's source tree. You can
00073 find details of how to do this at:
00074   http://www.xaraxtreme.org/developers/
00075 
00076 Prior to contributing your modifications, you will need to complete our
00077 contributor agreement. This can be found at:
00078   http://www.xaraxtreme.org/developers/contribute/
00079 
00080 Please note that Xara will not accept modifications which modify any of
00081 the text between the start and end of this header (marked
00082 XARAHEADERSTART and XARAHEADEREND).
00083 
00084 
00085 MARKS
00086 -----
00087 
00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara
00089 designs are registered or unregistered trademarks, design-marks, and/or
00090 service marks of Xara Group Ltd. All rights in these marks are reserved.
00091 
00092 
00093       Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK.
00094                         http://www.xara.com/
00095 
00096 =================================XARAHEADEREND============================
00097  */
00098 
00099 
00100 #include "camtypes.h"
00101 
00102 #include "cartprov.h"
00103 #include "camframe.h"
00104 #include "cartctl.h"
00105 
00106 CamArtProvider * CamArtProvider::m_ArtProvider = NULL;
00107 
00108 /*****************************************************************************
00109 
00110 This file contains the class for CamArtProvider, derived from
00111 wxEvtHandler. This contains a mapping allowing dialogs of ANY class
00112 derived from wxDialog to call the relevant bits of DialogManager.
00113 
00114 *****************************************************************************/
00115 
00116 IMPLEMENT_CLASS( CamArtProvider, wxEvtHandler )
00117 BEGIN_EVENT_TABLE(CamArtProvider, wxEvtHandler)
00118     EVT_CAMARTPROVIDER_GETBITMAP (wxID_ANY, CamArtProvider::GetBitmapEvent)
00119     EVT_CAMARTPROVIDER_INVALIDATEART (wxID_ANY, CamArtProvider::InvalidateArtEvent)
00120 END_EVENT_TABLE();
00121 
00122 DEFINE_EVENT_TYPE(wxEVT_CAMARTPROVIDER_GETBITMAP)
00123 DEFINE_EVENT_TYPE(wxEVT_CAMARTPROVIDER_INVALIDATEART)
00124 IMPLEMENT_DYNAMIC_CLASS( wxCamArtProviderEvent, wxEvent )
00125 
00126 /********************************************************************************************
00127 
00128 >   CamArtProvider::CamArtProvider()
00129 
00130 
00131     Author:     Alex_Bligh <alex@alex.org.uk>
00132     Created:    30/12/2005
00133     Inputs:     -
00134     Outputs:    -
00135     Returns:    -
00136     Purpose:    Constructor
00137     Errors:     -
00138     SeeAlso:    -
00139 
00140 ********************************************************************************************/
00141 
00142 CamArtProvider::CamArtProvider()
00143 {
00144     m_pHash = NULL;
00145     m_GetBitmapEventPending = FALSE;
00146     m_InvalidateArtEventPending = FALSE;
00147     m_pMissingImage = NULL;
00148 
00149     m_pMissingImage = new wxImage; // if this returns NULL, all missing bitmaps will be blank. Oh well
00150     if (m_pMissingImage) CamResource::LoadwxImage(*m_pMissingImage, _T("missing.png") );
00151     if (m_pMissingImage) m_pMissingBitmap=new wxBitmap(*m_pMissingImage, -1);
00152 
00153     m_pHash = new ResIDWithFlagsToBitmapPtr; // if this returns NULL, Init will whinge, so don't check
00154 }
00155 
00156 /********************************************************************************************
00157 
00158 >   CamArtProvider::~CamArtProvider()
00159 
00160 
00161     Author:     Alex_Bligh <alex@alex.org.uk>
00162     Created:    30/12/2005
00163     Inputs:     -
00164     Outputs:    -
00165     Returns:    -
00166     Purpose:    Destructor
00167     Errors:     -
00168     SeeAlso:    -
00169 
00170 ********************************************************************************************/
00171 
00172 CamArtProvider::~CamArtProvider()
00173 {
00174     if (m_pHash)
00175     {
00176         DeleteHashContents();
00177         if (m_pHash) delete m_pHash;
00178         m_pHash = NULL;
00179     }
00180     if (m_pMissingImage)
00181     {
00182         delete(m_pMissingImage);
00183         m_pMissingImage=NULL;
00184     }
00185     if (m_pMissingBitmap)
00186     {
00187         delete(m_pMissingBitmap);
00188         m_pMissingBitmap=NULL;
00189     }
00190 }
00191 
00192 /********************************************************************************************
00193 
00194 >   static wxColor CamArtProvider::DarkenColour(const wxColor& c, INT32 amount)
00195 
00196 
00197     Author:     Alex_Bligh <alex@alex.org.uk>
00198     Created:    30/12/2005
00199     Inputs:     c - a wxColour
00200                 amount - amount to darken it by
00201     Outputs:    a darkened colour
00202     Returns:    -
00203     Purpose:    Returns a darkened colour
00204     Errors:     -
00205     SeeAlso:    -
00206 
00207 ********************************************************************************************/
00208 
00209 wxColor CamArtProvider::DarkenColour(const wxColor& c, INT32 amount)
00210 {
00211     INT32 r = c.Red(), g = c.Green(), b = c.Blue();
00212     return wxColour((r*amount)/100, (g*amount)/100, (b*amount)/100);
00213 }
00214 
00215 /********************************************************************************************
00216 
00217 >   static wxColor CamArtProvider::LightenColour(const wxColor& c, INT32 amount)
00218 
00219 
00220     Author:     Alex_Bligh <alex@alex.org.uk>
00221     Created:    30/12/2005
00222     Inputs:     c - a wxColour
00223                 amount - amount to lighten it by
00224     Outputs:    a lightened colour
00225     Returns:    -
00226     Purpose:    Returns a lightened colour
00227     Errors:     -
00228     SeeAlso:    -
00229 
00230 ********************************************************************************************/
00231 
00232 wxColor CamArtProvider::LightenColour(const wxColor& c, INT32 amount)
00233 {
00234     INT32 r = 255-c.Red(), g = 255-c.Green(), b = 255-c.Blue();
00235     return wxColour(255-(r*amount)/100, 255-(g*amount)/100, 255-(b*amount)/100);
00236 }
00237 
00238 /********************************************************************************************
00239 
00240 >   static BOOL CamArtProvider::Init()
00241 
00242 
00243     Author:     Alex_Bligh <alex@alex.org.uk>
00244     Created:    30/12/2005
00245     Inputs:     None
00246     Outputs:    None
00247     Returns:    TRUE if succeeded, FALSE if fails
00248     Purpose:    Initialize the class
00249     Errors:     via wxMessageBox
00250     SeeAlso:    -
00251 
00252 ********************************************************************************************/
00253 
00254 BOOL CamArtProvider::Init()
00255 {
00256     ERROR3IF(m_ArtProvider, "Double Init of ArtProvider");
00257     m_ArtProvider=new(CamArtProvider);
00258     ERROR2IF(!m_ArtProvider, FALSE, "Cannot get an ArtProvider");
00259 
00260     return TRUE;
00261 }
00262 
00263 /********************************************************************************************
00264 
00265 >   static void CamArtProvider::DeInit()
00266 
00267 
00268     Author:     Alex_Bligh <alex@alex.org.uk>
00269     Created:    30/12/2005
00270     Inputs:     None
00271     Outputs:    None
00272     Returns:    TRUE if succeeded, FALSE if fails
00273     Purpose:    Initialize resources
00274     Errors:     via wxMessageBox
00275     SeeAlso:    -
00276 
00277 ********************************************************************************************/
00278 
00279 void CamArtProvider::DeInit()
00280 {
00281     if (m_ArtProvider)
00282     {
00283         delete m_ArtProvider;
00284         m_ArtProvider = FALSE;
00285     }
00286 }
00287 
00288 /********************************************************************************************
00289 
00290 >   void CamArtProvider::DeleteHashContents()
00291 
00292 
00293     Author:     Alex_Bligh <alex@alex.org.uk>
00294     Created:    30/12/2005
00295     Inputs:     -
00296     Outputs:    -
00297     Returns:    -
00298     Purpose:    Delete every hash table entry
00299     Errors:     -
00300     SeeAlso:    -
00301 
00302 Note we don't need to delete the bitmaps themselves - CamResource:: does that.
00303 Thus right now this routine does nothing much with the hash contents.
00304 
00305 ********************************************************************************************/
00306 
00307 void CamArtProvider::DeleteHashContents()
00308 {
00309     if (m_pHash)
00310     {
00311         ResIDWithFlagsToBitmapPtr::iterator current;
00312 
00313         while (!m_pHash->empty())
00314         {
00315             current = m_pHash->begin();
00316             // wxImage * s=current->second.m_pImage;
00317             m_pHash->erase(current);
00318             // delete s;  -- we don't need to do this, CamResource:: does this
00319         }
00320         // for good measure
00321         m_pHash->clear();
00322         
00323         delete (m_pHash);
00324         m_pHash = NULL;
00325     }
00326 }
00327 
00328 /********************************************************************************************
00329 
00330 >   void CamArtProvider::ArtLoad(BOOL newbitmaps = FALSE, BOOL defer = TRUE)
00331 
00332 
00333     Author:     Alex_Bligh <alex@alex.org.uk>
00334     Created:    30/12/2005
00335     Inputs:     newbitmaps - set TRUE if we should forget cache of all bitmaps that were
00336                              missing last time. Also causes existing pending event flag
00337                              to be ignored in case an event got lost (should never happen).
00338                 defer      - set TRUE if the art load is to be deferred
00339     Outputs:    -
00340     Returns:    -
00341     Purpose:    Schedule a GetBitmap event, unless one is already scheduled
00342     Errors:     -
00343     SeeAlso:    -
00344 
00345 ********************************************************************************************/
00346 
00347 void CamArtProvider::ArtLoad(BOOL newbitmaps, BOOL defer)
00348 {
00349     // If we already have an event pending, don't generate a new one
00350     if (m_GetBitmapEventPending && !newbitmaps) return;
00351 
00352     if (newbitmaps && m_pMissingImage && m_pHash && !m_pHash->empty())
00353     {
00354         ResIDWithFlagsToBitmapPtr::iterator current;
00355 
00356         for( current = m_pHash->begin(); current != m_pHash->end(); ++current )
00357         {
00358             // we don't need to worry about memory management as deleting the
00359             // bitmaps are CamResource::'s responsibility
00360             if (current->second.m_pImage == m_pMissingImage)
00361                 m_pMissingImage = NULL; // mark as required to be loaded on the event
00362         }
00363     }
00364 
00365     // Send ourselves a deferred event
00366     m_GetBitmapEventPending = TRUE;
00367     wxCamArtProviderEvent event (wxEVT_CAMARTPROVIDER_GETBITMAP, 0, defer);
00368     if (defer)
00369         AddPendingEvent(event);
00370     else
00371         ProcessEvent(event);    
00372 }
00373 
00374 
00375 /********************************************************************************************
00376 
00377 >   CamArtProvider::GetBitmapEvent(wxCamArtProviderEvent& event)
00378 
00379 
00380     Author:     Alex_Bligh <alex@alex.org.uk>
00381     Created:    30/12/2005
00382     Inputs:     event - the wxEvent
00383     Outputs:    -
00384     Returns:    -
00385     Purpose:    Called when we need to load some art
00386     Errors:     -
00387     SeeAlso:    -
00388 
00389 ********************************************************************************************/
00390 
00391 
00392 void CamArtProvider::GetBitmapEvent(wxCamArtProviderEvent& event)
00393 {
00394     if (m_pHash && !m_pHash->empty())
00395     {
00396         BOOL FoundBitmapToLoad = FALSE;
00397         ResIDWithFlagsToBitmapPtr::iterator current;
00398         for( current = m_pHash->begin(); current != m_pHash->end(); ++current )
00399         {
00400             if (!current->second.m_pImage) // we have no blank bitmap
00401             {
00402                 FoundBitmapToLoad = TRUE;
00403 
00404 //              ResourceID r = GetResourceID(current->first);
00405 //              CamArtFlags f = GetFlags(current->first);
00406 //              TRACE(_T("Hash for bitmap 0x%x:%d %s"),f,r,CamResource::GetObjectName(r));
00407 
00408                 wxImage * pBitmap = MakeBitmap(current->first);
00409                 current->second.m_pImage = pBitmap?pBitmap:m_pMissingImage;
00410             }
00411         }
00412 
00413         if (FoundBitmapToLoad)
00414         {
00415             if (!m_InvalidateArtEventPending)
00416             {
00417                 m_InvalidateArtEventPending = TRUE;
00418                 BOOL defer=!event.m_deferred; //Defer the invalidate if this is immediate
00419                 wxCamArtProviderEvent event (wxEVT_CAMARTPROVIDER_INVALIDATEART, 0, defer);
00420                 if (defer)
00421                     AddPendingEvent(event);
00422                 else
00423                     ProcessEvent(event);    
00424             }
00425         }
00426     }
00427     m_GetBitmapEventPending=FALSE;
00428 }
00429 
00430 /********************************************************************************************
00431 
00432 >   CamArtProvider::GetBitmapEvent(wxCamArtProviderEvent& event)
00433 
00434 
00435     Author:     Alex_Bligh <alex@alex.org.uk>
00436     Created:    30/12/2005
00437     Inputs:     event - the wxEvent
00438     Outputs:    -
00439     Returns:    -
00440     Purpose:    Called when we need to load some art
00441     Errors:     -
00442     SeeAlso:    -
00443 
00444 ********************************************************************************************/
00445 
00446 
00447 void CamArtProvider::InvalidateArtEvent(wxCamArtProviderEvent& event)
00448 {
00449     m_InvalidateArtEventPending = FALSE;
00450     InvalidateAllArt();
00451 }
00452 
00453 /********************************************************************************************
00454 
00455 >   void CamArtProvider::InvalidateAllArt()
00456 
00457 
00458     Author:     Alex_Bligh <alex@alex.org.uk>
00459     Created:    30/12/2005
00460     Inputs:     -
00461     Outputs:    -
00462     Returns:    -
00463     Purpose:    Invalidates every window which has art in it
00464     Errors:     -
00465     SeeAlso:    -
00466 
00467 Note this function should do a broadcast to all, which will allow others to invalidate
00468 themselves.
00469 
00470 ********************************************************************************************/
00471 
00472 
00473 void CamArtProvider::InvalidateAllArt()
00474 {
00475     wxWindow * pWindow = CCamFrame::GetMainFrame();
00476     if (pWindow) InvalidateAllArtInChildren(pWindow);
00477 
00478     // Broadcast an art changing message here!
00479 
00480 }
00481 
00482 /********************************************************************************************
00483 
00484 >   void CamArtProvider::InvalidateAllArtInChildren(wxWindow * pWindow)
00485 
00486 
00487     Author:     Alex_Bligh <alex@alex.org.uk>
00488     Created:    30/12/2005
00489     Inputs:     event - the wxEvent
00490     Outputs:    -
00491     Returns:    -
00492     Purpose:    Invalidates every window which has art in it
00493     Errors:     -
00494     SeeAlso:    -
00495 
00496 Note this function should do a broadcast to all, which will allow others to invalidate
00497 themselves.
00498 
00499 ********************************************************************************************/
00500 
00501 
00502 void CamArtProvider::InvalidateAllArtInChildren(wxWindow * pWindow)
00503 {
00504     // Process this one
00505     if (pWindow->IsKindOf(CLASSINFO(wxCamArtControl)))
00506         ((wxCamArtControl *)pWindow)->NewBitmap();
00507 
00508     // Now process children if any
00509     wxWindowList::Node * pNode = pWindow->GetChildren().GetFirst();
00510     while (pNode)
00511     {
00512         InvalidateAllArtInChildren(pNode->GetData());
00513         pNode = pNode->GetNext();
00514     }
00515     return;
00516 }
00517 
00518 /********************************************************************************************
00519 
00520 >   void CamArtProvider::EnsureBitmapLoaded(ResourceID Resource, BOOL SkipArtLoad=FALSE)
00521 
00522 
00523     Author:     Alex_Bligh <alex@alex.org.uk>
00524     Created:    30/12/2005
00525     Inputs:     Resource - the ResourceID of the art to ensure is loaded
00526     Outputs:    -
00527     Returns:    -
00528     Purpose:    Passes an event to DialogManager::Event
00529     Errors:     -
00530     SeeAlso:    -
00531 
00532 ********************************************************************************************/
00533 
00534 
00535 void CamArtProvider::EnsureBitmapLoaded(ResourceID Resource, BOOL SkipArtLoad)
00536 {
00537     UINT32 f;
00538     for (f = 0; f<CAF_CACHE_MAX; f++)
00539     {
00540         FindBitmap(Resource, (CamArtFlags)f, SkipArtLoad);  // Find all the variants of the bitmap, thus ensuring a load
00541     }
00542 }
00543 
00544 /********************************************************************************************
00545 
00546 >   void CamArtProvider::EnsureChildBitmapsLoaded(wxWindow * pWindow = NULL, BOOL SkipArtLoad=FALSE)
00547 
00548 
00549     Author:     Alex_Bligh <alex@alex.org.uk>
00550     Created:    30/12/2005
00551     Inputs:     event - the wxEvent
00552     Outputs:    -
00553     Returns:    -
00554     Purpose:    Invalidates every window which has art in it
00555     Errors:     -
00556     SeeAlso:    -
00557 
00558 Note this function should do a broadcast to all, which will allow others to invalidate
00559 themselves. Note that we bunch up all the art loading until the end by ensuring that
00560 internally we call with SkipArtLoad set.
00561 
00562 ********************************************************************************************/
00563 
00564 
00565 void CamArtProvider::EnsureChildBitmapsLoaded(wxWindow * pWindow, BOOL SkipArtLoad)
00566 {
00567     if (!pWindow)
00568         pWindow = CCamFrame::GetMainFrame();
00569 
00570     if (!pWindow) return;
00571 
00572     // Process this one
00573     if ( (pWindow->IsKindOf(CLASSINFO(wxCamArtControl))) &&
00574          !(((wxCamArtControl*)pWindow)->GetStyle() & wxCACS_TEXT) ) // don't bother finding bitmaps for text ones, as there isn't one!
00575         EnsureBitmapLoaded((ResourceID)(pWindow->GetId()), TRUE); // always skip the art load
00576 
00577     // Now process children if any
00578     wxWindowList::Node * pNode = pWindow->GetChildren().GetFirst();
00579     while (pNode)
00580     {
00581         EnsureChildBitmapsLoaded(pNode->GetData(), TRUE); // Always skip the art load
00582         pNode = pNode->GetNext();
00583     }
00584 
00585     if (!SkipArtLoad)
00586         ArtLoad(FALSE, FALSE);
00587 
00588     return;
00589 }
00590 
00591 /********************************************************************************************
00592 
00593 >   void CamArtProvider::ReloadAllArt()
00594 
00595 
00596     Author:     Alex_Bligh <alex@alex.org.uk>
00597     Created:    30/12/2005
00598     Inputs:     -
00599     Outputs:    -
00600     Returns:    -
00601     Purpose:    Reloads all the art
00602     Errors:     -
00603     SeeAlso:    -
00604 
00605 ********************************************************************************************/
00606 
00607 void CamArtProvider::ReloadAllArt()
00608 {
00609     m_GetBitmapEventPending=FALSE; // to be sure
00610     DeleteHashContents();
00611     EnsureChildBitmapsLoaded();
00612 }
00613 
00614 /********************************************************************************************
00615 
00616 >   ResIDWithFlagsToBitmapPtr::iterator CamArtProvider::Find(ResourceID Resource, CamArtFlags Flags = 0, BOOL SkipArtLoad=FALSE)
00617 
00618 
00619     Author:     Alex_Bligh <alex@alex.org.uk>
00620     Created:    30/12/2005
00621     Inputs:     Resource - the resource ID to find
00622                 Flags - the flags to find
00623     Outputs:    -
00624     Returns:    a pointer to the bitmap that has been foudn
00625     Purpose:    Finds the cached bitmap with the relevant resource ID & flags
00626     Errors:     -
00627     SeeAlso:    -
00628 
00629 may return NULL if there is no default "missing bitmap" that could be loaded
00630 
00631 ********************************************************************************************/
00632 
00633 
00634 ResIDWithFlagsToBitmapPtr::iterator CamArtProvider::Find(ResourceID Resource, CamArtFlags Flags, BOOL SkipArtLoad)
00635 {
00636     ResourceIDWithFlags f = CombineFlags(Resource, (CamArtFlags)(Flags & (CAF_CACHE_MAX-1)));
00637     if (!m_pHash) return m_pHash->end();
00638 
00639     // get the bitmap from the hash
00640     ResIDWithFlagsToBitmapPtr::iterator i=m_pHash->find(f);
00641     if (i==m_pHash->end())
00642     {
00643         // Oh dear, we haven't found an entry. We thus create one and schedule a load
00644         ImageAndBitmap IandB;
00645         (*m_pHash)[f]=IandB;
00646         if (!SkipArtLoad)
00647             ArtLoad(FALSE, FALSE);
00648         // See if it's appeared
00649         i=m_pHash->find(f);
00650     }
00651 
00652     return i;
00653 }
00654 
00655 /********************************************************************************************
00656 
00657 >   wxImage * CamArtProvider::FindImage(ResourceID Resource, CamArtFlags Flags = 0, BOOL SkipArtLoad=FALSE)
00658 
00659 
00660     Author:     Alex_Bligh <alex@alex.org.uk>
00661     Created:    30/12/2005
00662     Inputs:     Resource - the resource ID to find
00663                 Flags - the flags to find
00664     Outputs:    -
00665     Returns:    a pointer to the bitmap that has been foudn
00666     Purpose:    Finds the cached bitmap with the relevant resource ID & flags
00667     Errors:     -
00668     SeeAlso:    -
00669 
00670 may return NULL if there is no default "missing bitmap" that could be loaded
00671 
00672 ********************************************************************************************/
00673 
00674 
00675 wxImage * CamArtProvider::FindImage(ResourceID Resource, CamArtFlags Flags, BOOL SkipArtLoad)
00676 {
00677     ResIDWithFlagsToBitmapPtr::iterator i=Find(Resource, Flags, SkipArtLoad);
00678     if (i==m_pHash->end())
00679     {
00680         return m_pMissingImage;
00681     }
00682     wxImage *pImage = i->second.m_pImage;
00683 
00684     return pImage?pImage:m_pMissingImage;
00685 }
00686 
00687 /********************************************************************************************
00688 
00689 >   wxImage * CamArtProvider::FindBitmap(ResourceID Resource, CamArtFlags Flags = 0, BOOL SkipArtLoad=FALSE)
00690 
00691 
00692     Author:     Alex_Bligh <alex@alex.org.uk>
00693     Created:    30/12/2005
00694     Inputs:     Resource - the resource ID to find
00695                 Flags - the flags to find
00696     Outputs:    -
00697     Returns:    a pointer to the bitmap that has been foudn
00698     Purpose:    Finds the cached bitmap with the relevant resource ID & flags
00699     Errors:     -
00700     SeeAlso:    -
00701 
00702 may return NULL if there is no default "missing bitmap" that could be loaded
00703 
00704 We look for an image, and if there is an attached bitmap, use that, else make one
00705 
00706 ********************************************************************************************/
00707 
00708 
00709 wxBitmap * CamArtProvider::FindBitmap(ResourceID Resource, CamArtFlags Flags, BOOL SkipArtLoad)
00710 {
00711     ResIDWithFlagsToBitmapPtr::iterator i=Find(Resource, Flags, SkipArtLoad);
00712     if (i==m_pHash->end())
00713     {
00714         return m_pMissingBitmap;
00715     }
00716     wxBitmap *pBitmap = i->second.m_pBitmap;
00717     if (pBitmap) return pBitmap;
00718 
00719     // No bitmap. Do we have an image?
00720     wxImage *pImage = i->second.m_pImage;
00721 
00722     if (!pImage || (pImage==m_pMissingImage))
00723         return m_pMissingBitmap;
00724 
00725     // OK make a bitmap
00726     pBitmap = new wxBitmap(*pImage, -1); // for now, always use screen depth, not least as GDK doesn't support anything except this & 1bpp
00727     if (!pBitmap) return m_pMissingBitmap;
00728 
00729     i->second.m_pBitmap=pBitmap;
00730     return pBitmap;
00731 }
00732 
00733 /********************************************************************************************
00734 
00735 >   void CamArtProvider::Draw(wxDC& dc, const wxRect & rect, ResourceID Resource, CamArtFlags Flags = 0, const wxString &text = wxEmptyString)
00736 
00737 
00738     Author:     Alex_Bligh <alex@alex.org.uk>
00739     Created:    30/12/2005
00740     Inputs:     dc - the wxDC to draw into
00741                 Resource - the ResourceID to load
00742                 CamArtFlags - the flags to use for drawing
00743                 InternalBorder - the internal border (in pixels) - see note
00744     Outputs:    -
00745     Returns:    pointer to a string containing the event number
00746     Purpose:    Draws the art into the appropriate DC
00747     Errors:     -
00748     SeeAlso:    -
00749 
00750 Note that the internal border is the TOTAL internal border (i.e. left plus right). Border
00751 pixels will be allocated preferentially on left and top, to right and bottom. Rect should
00752 already have been inflated (wxCamArtControl does this by increasing its client area).
00753 
00754 ********************************************************************************************/
00755 
00756 void CamArtProvider::Draw(wxDC& dc, const wxRect & rect, ResourceID Resource, CamArtFlags Flags, const wxString &text)
00757 {
00758     dc.SetBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
00759     dc.SetPen(*wxTRANSPARENT_PEN);
00760 //  dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height);
00761     
00762 //  dc.SetBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
00763     dc.SetBrush(*wxTRANSPARENT_BRUSH); // Needed in case we need to paint 3D furniture, but not the button top (ALWAYS3D)
00764 
00765     wxRect brect = rect;
00766 
00767     UINT32 bitmapoffsetX=0;
00768     UINT32 bitmapoffsetY=0;
00769 
00770     if ((Flags & CAF_PUSHBUTTON) && !rect.IsEmpty())
00771     {
00772         // 3Dness
00773         brect.width-=1;
00774         brect.height-=1;
00775         
00776         if (Flags & CAF_SELECTED)
00777         {
00778             // It's pushed in
00779             brect.x++;
00780             brect.y++;
00781         }
00782 
00783         UINT32 InternalBorderX = (Flags & CAF_NOINTERNALBORDER)?0:2;
00784         UINT32 InternalBorderY = (Flags & CAF_NOINTERNALBORDER)?0:1;
00785 
00786         bitmapoffsetX=1+((InternalBorderX+1)>>1); // this is a completely independent offset to the brect stuff, which gives the bitmap a border
00787         bitmapoffsetY=1+((InternalBorderY+1)>>1); // this is a completely independent offset to the brect stuff, which gives the bitmap a border
00788 
00789 //      BOOL FaceSelected = ( (Flags & CAF_SELECTED) || (Flags & CAF_BUTTONHOVER) );
00790 //      BOOL Border3D = ( (Flags & CAF_SELECTED) || (Flags & CAF_ALWAYS3D));
00791 
00792         BOOL FaceSelected = ( (Flags & CAF_SELECTED) || ((Flags & CAF_ALWAYS3D) && (Flags & CAF_BUTTONHOVER)) ); // highlight face on hover if always3D
00793         BOOL Border3D = ( (Flags & CAF_SELECTED) || (Flags & CAF_ALWAYS3D) || (Flags & CAF_BUTTONHOVER));
00794 
00795         // Change the brush if the face is selected
00796         if (FaceSelected)
00797         {
00798             if (Flags & CAF_TOOLBACKGROUND)
00799                 dc.SetBrush(wxColour(255,255,192)); // A light yellow - we should load this from somewhere else
00800             else
00801             {   
00802                 if (Flags & CAF_BUTTONHOVER)
00803                     dc.SetBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_3DHIGHLIGHT));
00804                 else    
00805                     dc.SetBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE));
00806             }
00807         }
00808 
00809         if (Border3D)
00810         {
00811             // draw the light highlights
00812             dc.SetPen(wxSystemSettings::GetColour((Flags & CAF_SELECTED)?wxSYS_COLOUR_3DHIGHLIGHT:wxSYS_COLOUR_3DDKSHADOW));
00813             // draw the background behind the button undisplaced
00814             dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height);
00815             // now draw the left & top bits
00816             dc.SetPen(wxSystemSettings::GetColour((Flags & CAF_SELECTED)?wxSYS_COLOUR_3DDKSHADOW:wxSYS_COLOUR_3DHIGHLIGHT));
00817             dc.DrawLine(rect.x, rect.y, rect.x+rect.width-1, rect.y);
00818             dc.DrawLine(rect.x, rect.y, rect.x, rect.y+rect.height-1);
00819         }
00820         else if (FaceSelected) // if not FaceSelected, we've already drawn it
00821         {
00822             // draw the background behind the button displaced
00823             dc.DrawRectangle(brect.x, brect.y, brect.width, brect.height);
00824         }
00825     }
00826 
00827     // Now apply justification to the object
00828     wxRect BestSize(GetSize(Resource, Flags, text));
00829     if (BestSize.width != rect.width)
00830     {
00831         if (Flags & CAF_RIGHT)
00832         {
00833             bitmapoffsetX += (rect.width-BestSize.width);
00834         }
00835         else if (Flags & CAF_LEFT)
00836         {
00837             // do nothing
00838         }
00839         else
00840         {
00841             bitmapoffsetX += (rect.width-BestSize.width)/2;
00842         }   
00843     }   
00844     if (BestSize.height != rect.height)
00845     {
00846         if (Flags & CAF_BOTTOM)
00847         {
00848             bitmapoffsetY += (rect.height-BestSize.height);
00849         }
00850         else if (Flags & CAF_TOP)
00851         {
00852             // do nothing
00853         }
00854         else
00855         {
00856             bitmapoffsetY += (rect.height-BestSize.height)/2;
00857         }   
00858     }   
00859 
00860     if (Flags & CAF_TEXT)
00861     {
00862         // The max width is the width of the entire control, less the internal border width
00863         wxCoord MaxWidth = rect.GetWidth() - GetBorderSize(Flags).GetWidth();
00864         if (MaxWidth<0)
00865             MaxWidth=0;
00866         wxString ctext = GetTextInfoOrDraw(Resource, Flags, dc, TRUE, NULL, NULL, brect.x+bitmapoffsetX, brect.y+bitmapoffsetY, MaxWidth, text);
00867     }
00868     else
00869     {
00870         // Get the bitmap with the correct flags. We here pretend the button is selected if we are
00871         // hovering. We can't do this in the control (grrr...) because else by the time the flags get
00872         // here we cannot distinguish selection from hover, which means we slab wrongly
00873         wxBitmap *pBitmap = FindBitmap(Resource, (CamArtFlags)(Flags|((Flags & CAF_BUTTONHOVER)?CAF_SELECTED:0) ));
00874         
00875         // plot the bitmap
00876         if (pBitmap)
00877             dc.DrawBitmap(*pBitmap, brect.x+bitmapoffsetX, brect.y+bitmapoffsetY, TRUE);
00878     }
00879 }
00880 
00881 /********************************************************************************************
00882 
00883 >   wxSize CamArtProvider::GetSize(ResourceID r, CamArtFlags Flags=CAF_DEFAULT, const wxString &text = wxEmptyString)
00884 
00885 
00886     Author:     Alex_Bligh <alex@alex.org.uk>
00887     Created:    25/01/2005
00888     Inputs:     r - the resource
00889                 Flags - the flags
00890     Outputs:    -
00891     Returns:    The size of the control
00892     Purpose:    -
00893     Errors:     -
00894     SeeAlso:    -
00895 
00896 Note that the internal border is the TOTAL internal border (i.e. left plus right). Border
00897 pixels will be allocated preferentially on left and top, to right and bottom. Rect should
00898 already have been inflated (wxCamArtControl does this by increasing its client area).
00899 
00900 ********************************************************************************************/
00901 
00902 wxSize CamArtProvider::GetSize(ResourceID r, CamArtFlags Flags, const wxString &text)
00903 {
00904     wxCoord w=24;
00905     wxCoord h=24;
00906 
00907     if (Flags & CAF_TEXT)
00908     {
00909         wxScreenDC dc;
00910         wxString ctext = GetTextInfoOrDraw(r, Flags, dc, FALSE, &w, &h, 0, 0, -1, text);
00911     }
00912     else
00913     {
00914         wxBitmap * pBitmap=FindBitmap(r, Flags);
00915         if (pBitmap)
00916         {
00917             w=pBitmap->GetWidth();
00918             h=pBitmap->GetHeight();
00919         }
00920     }
00921 
00922     wxSize Border=GetBorderSize(Flags);
00923     return wxSize(w+Border.GetWidth(), h+Border.GetHeight());
00924 }
00925 
00926 /********************************************************************************************
00927 
00928 >   wxSize CamArtProvider::GetBorderSize(CamArtFlags Flags=CAF_DEFAULT)
00929 
00930 
00931     Author:     Alex_Bligh <alex@alex.org.uk>
00932     Created:    25/01/2005
00933     Inputs:     Flags - the flags
00934     Outputs:    -
00935     Returns:    The size of the border around the control
00936     Purpose:    -
00937     Errors:     -
00938     SeeAlso:    -
00939 
00940 Note that the internal border is the TOTAL internal border (i.e. left plus right). Border
00941 pixels will be allocated preferentially on left and top, to right and bottom. Rect should
00942 already have been inflated (wxCamArtControl does this by increasing its client area).
00943 
00944 ********************************************************************************************/
00945 
00946 wxSize CamArtProvider::GetBorderSize(CamArtFlags Flags /*=CAF_DEFAULT*/)
00947 {
00948     UINT32 InternalBorderX = (Flags & CAF_NOINTERNALBORDER)?0:2;
00949     UINT32 InternalBorderY = (Flags & CAF_NOINTERNALBORDER)?0:1;
00950     // 3 extra pixels for push buttons, 2 border (one on each side) and one for push displacement
00951     UINT32 extraX=InternalBorderX+3*((Flags & CAF_ALWAYS3D) || (Flags & CAF_PUSHBUTTON)); // 3 or 0
00952     UINT32 extraY=InternalBorderY+3*((Flags & CAF_ALWAYS3D) || (Flags & CAF_PUSHBUTTON)); // 3 or 0
00953     return wxSize(extraX, extraY);
00954 }
00955 
00956 /********************************************************************************************
00957 
00958 >   wxString CamArtProvider::GetTextInfoOrDraw(ResourceID r, wxDC &dc,  BOOL Draw=FALSE, wxCoord *w=NULL, wxCoord *h=NULL,
00959                                                wxCoord x=0, wxCoord y=0, wxCoord MaxWidth=-1, const wxString &text = wxEmptyString)
00960 
00961 
00962     Author:     Alex_Bligh <alex@alex.org.uk>
00963     Created:    24/04/2006
00964     Inputs:     r - the resource
00965                 Flags - the flags
00966                 Draw = TRUE to draw the text
00967                 x, y - location to draw the text (if Draw is set)
00968                 MaxWidth - the maximum width or the text (use -1 when calculating for no max width)
00969     Outputs:    w, h, pointers to fill in (can be NULL) for the text extent. Either both or neither must be NULL
00970     Returns:    The text
00971     Purpose:    Sets up the DC and returns the text
00972     Errors:     -
00973     SeeAlso:    -
00974 
00975 ********************************************************************************************/
00976 
00977 wxString CamArtProvider::GetTextInfoOrDraw(ResourceID r, CamArtFlags f, wxDC &dc, BOOL Draw/*=FALSE*/, wxCoord *w, wxCoord *h, wxCoord x, wxCoord y,
00978                                             wxCoord MaxWidth /*= -1*/, const wxString &text)
00979 {
00980     // find the name by looking up the ID as a string
00981     const TCHAR * tcname=text;
00982 
00983     if (w) *w=0;
00984     if (h) *h=0;
00985 
00986     if (text.IsEmpty())
00987     {
00988         tcname = CamResource::GetTextFail(r);
00989         if (!tcname || ( (tcname[0]==_T('-')) && !tcname[1]) )
00990         {
00991             // default to object name
00992             tcname = CamResource::GetObjectNameFail(r);
00993         }
00994         
00995         if (!tcname)
00996         {
00997             // If this goes off, then somehow we've been passed a resource ID without a reverse
00998             // bitmap lookup. This can normally only happen if the resource ID is corrupted, or
00999             // the resources are corrupted
01000             ERROR3_PF(("Cannot get text for resource %d",r));
01001             return wxEmptyString;
01002         }
01003     }
01004 
01005     dc.SetTextForeground(wxSystemSettings::GetColour((f & CAF_GREYED)?wxSYS_COLOUR_GRAYTEXT:wxSYS_COLOUR_BTNTEXT));
01006     wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
01007     font.SetPointSize((f & CAF_HALFHEIGHT)?7:8);
01008     dc.SetFont(font);
01009 
01010     wxString RenderText(tcname);
01011 
01012     if (!(f & CAF_STATUSBARTEXT))
01013     {
01014         if (h && w)
01015             dc.GetTextExtent(RenderText, w, h);
01016     
01017         if (Draw)
01018             dc.DrawText(RenderText, x, y);
01019     }
01020     else
01021     {
01022         // It's status bar text. We have to go through the tokens individually
01023 
01024         // First tokenize the string
01025         INT32 i=0;
01026         wxArrayString Tokens;
01027         wxArrayString Separators;
01028         wxString SubString=wxEmptyString;
01029         INT32 BoldBreak=-1;
01030         for (i=0; i<(INT32)(RenderText.Length()); i++)
01031         {
01032             wxChar c = RenderText[i];
01033             if ( (c==_T(';')) ||
01034                  ((c==_T(':')) && (i<((INT32)RenderText.Length())-1) && (RenderText[i+1]==_T(':')) )
01035                 )
01036             {
01037                 // We found a separator
01038                 Tokens.Add(SubString);
01039                 Separators.Add(wxString(c));
01040 
01041                 // Was it a colon separator?
01042                 if (c==_T(':'))
01043                 {
01044                     // Remember it's now bold up to here
01045                     BoldBreak=Tokens.GetCount();
01046                     // Skip over the second colon
01047                     i++;
01048                 }
01049 
01050                 SubString=wxEmptyString;
01051             }
01052             else
01053                 SubString+=c; // It's not a separator, add it to the substring
01054         }
01055 
01056         // add the final token
01057         if (!SubString.IsEmpty())
01058         {
01059             Tokens.Add(SubString);
01060             Separators.Add(wxEmptyString);
01061         }
01062 
01063         BOOL Stop = FALSE;
01064         wxCoord CumWidth = 0; // The cumulative width used so far
01065         wxCoord MaxHeight = 0; // The max height used so far
01066         wxFont BoldFont = font;
01067         BoldFont.SetWeight(wxFONTWEIGHT_BOLD);
01068 
01069         for (i=0; i<(INT32)(Tokens.GetCount()) && !Stop; i++)
01070         {
01071             wxString TextBlob = Tokens[i] + Separators[i];
01072 
01073             // Set the font up
01074             if (i<BoldBreak)
01075                 dc.SetFont(BoldFont);
01076             else
01077                 dc.SetFont(font);
01078 
01079             // Find out how large this blob is
01080             wxCoord ww=0;
01081             wxCoord hh=0;
01082             dc.GetTextExtent(TextBlob, &ww, &hh);
01083 
01084             // Does it fit (or do we force it to fit because it is the first text)
01085             if ((MaxWidth<0) || (i==0) || (CumWidth+ww<=MaxWidth))
01086             {
01087                 // Draw it if necessary
01088                 if (Draw)
01089                     dc.DrawText(TextBlob, x+CumWidth, y);
01090 
01091                 // Account for its width
01092                 CumWidth+=ww;
01093                 if (hh>MaxHeight)
01094                     MaxHeight=hh;
01095             }
01096             else
01097                 Stop=TRUE;
01098         }
01099         if (h)
01100             *h = MaxHeight;
01101         if (w)
01102             *w = CumWidth;
01103     }
01104 
01105     return RenderText;
01106 }
01107 
01108 /********************************************************************************************
01109 
01110 >   wxImage * CamArtProvider::MakeBitmap(ResourceIDWithFlags ResWithFlags, BOOL Grey=FALSE)
01111 
01112 
01113     Author:     Alex_Bligh <alex@alex.org.uk>
01114     Created:    30/12/2005
01115     Inputs:     ResWithFlags - the hash key to make a bitmap for (ResourceID combined with flags)
01116                 Grey - true if we should grey (in software) the image we find. Don't set this
01117                        when calling, set CAF_GREYED which will use a greyed preprepared version
01118                        if available
01119     Outputs:    -
01120     Returns:    a pointer to the bitmap, or NULL if one could not be made
01121     Purpose:    Makes a bitmap from the appropraite resource
01122     Errors:     -
01123     SeeAlso:    -
01124 
01125 This routine is abstracted to allow an easy switch to vector art. Simlarly, it is only
01126 called from the main event loop, so we are safe to muck arround with the current document
01127 etc. so we can do a true render.
01128 
01129 ********************************************************************************************/
01130 
01131 wxImage * CamArtProvider::MakeBitmap(ResourceIDWithFlags ResWithFlags)
01132 {
01133     ResourceID r = GetResourceID(ResWithFlags);
01134     CamArtFlags f = GetFlags(ResWithFlags);
01135     wxImage * pBitmap = NULL;
01136 
01137     // find the name by looking up the ID as a string
01138     const TCHAR * tcname = NULL; /*CamResource::GetTextFail(r);*/
01139     if (!tcname || ( (tcname[0]==_T('-')) && !tcname[1]) )
01140     {
01141         // default to object name
01142         tcname = CamResource::GetObjectNameFail(r);
01143     }
01144 
01145     if (!tcname)
01146     {
01147         // If this goes off, then somehow we've been passed a resource ID without a reverse
01148         // bitmap lookup. This can normally only happen if the resource ID is corrupted, or
01149         // the resources are corrupted
01150         ERROR3_PF(("Cannot get bitmap name for resource %d",r));
01151         delete pBitmap;
01152         return FALSE;
01153     }
01154 
01155     wxString basename(tcname);
01156     wxString resname;
01157 
01158     // Iterate over all extensions
01159     INT32 ext;
01160     for (ext=0; ext<(INT32)(CamResource::BitmapExtensions.GetCount()); ext++)
01161     {
01162         resname=CamResource::MakeBitmapString(basename, MakeBitmapFlagString(f), CamResource::BitmapExtensions[ext]);
01163     
01164         pBitmap=CamResource::GetCachedBitmap(resname.c_str());
01165         if (pBitmap) return pBitmap;
01166     
01167         // OK, it didn't work. Try deleting the flags in order and seeing whether
01168         // that works. Note each of these will itself try deleting flags. Thus recursively
01169         // we work our way down to the base bitmap.
01170     
01171 #ifdef _DEBUG
01172         static INT32 recursion=0;
01173         recursion++;
01174         ERROR3IF(recursion>16,"Too much recursion in CamArtProvider::MakeBitmap");
01175 #endif
01176         if (!pBitmap && (f & CAF_SELECTED)) pBitmap=MakeBitmap(CombineFlags(r, (CamArtFlags)(f & ~CAF_SELECTED)));
01177         if (!pBitmap && (f & CAF_FOCUS)) pBitmap=MakeBitmap(CombineFlags(r, (CamArtFlags)(f & ~CAF_FOCUS)));
01178         if (!pBitmap && (f & CAF_SMALL)) pBitmap=MakeBitmap(CombineFlags(r, (CamArtFlags)(f & ~CAF_SMALL)));
01179         if (!pBitmap && (f & CAF_GREYED)) pBitmap=MakeBitmap(CombineFlags(r, (CamArtFlags)(f & ~CAF_GREYED)));
01180 #if _DEBUG
01181         recursion--;
01182 #endif
01183         if (pBitmap) return pBitmap;
01184     }   
01185 
01186     return NULL;
01187 }
01188 
01189 /********************************************************************************************
01190 
01191 >   static CamArtFlags CamArtProvider::GetBitmapFlags(const wxString &str);
01192 
01193 
01194     Author:     Alex_Bligh <alex@alex.org.uk>
01195     Created:    24/01/2005
01196     Inputs:     str - sting to look at
01197     Outputs:    None
01198     Returns:    Flags associated with a bitmap string
01199     Purpose:    
01200     Errors:     -
01201     SeeAlso:    -
01202 
01203 ********************************************************************************************/
01204 
01205 CamArtFlags CamArtProvider::GetBitmapFlags(const wxString &str)
01206 {
01207     wxString ext=CamResource::GetBitmapFlagString(str);
01208     return (CamArtFlags)(
01209             ((ext.Find('s')>=0)?CAF_SMALL:0) |
01210             ((ext.Find('f')>=0)?CAF_FOCUS:0) |
01211             ((ext.Find('x')>=0)?CAF_SELECTED:0) |
01212             ((ext.Find('g')>=0)?CAF_GREYED:0) |
01213             0);
01214 }
01215 
01216 /********************************************************************************************
01217 
01218 >   static CamArtFlags CamArtProvider::MakeBitmapFlagString(const CamArtFlags flags)
01219 
01220 
01221     Author:     Alex_Bligh <alex@alex.org.uk>
01222     Created:    24/01/2005
01223     Inputs:     flags - the flags to look at
01224     Outputs:    None
01225     Returns:    Flags string associated with a bitmap
01226     Purpose:    
01227     Errors:     -
01228     SeeAlso:    -
01229 
01230 ********************************************************************************************/
01231 
01232 wxString CamArtProvider::MakeBitmapFlagString(const CamArtFlags flags)
01233 {
01234     wxString mod;
01235 
01236     if (flags & CAF_SMALL) mod+=_T("s");
01237     if (flags & CAF_FOCUS) mod+=_T("f");
01238     if (flags & CAF_SELECTED) mod+=_T("x");
01239     if (flags & CAF_GREYED) mod+=_T("g");
01240     return mod;
01241 }
01242 

Generated on Sat Nov 10 03:48:13 2007 for Camelot by  doxygen 1.4.4