1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     XML resources 
   4 // Author:      Vaclav Slavik 
   7 // Copyright:   (c) 2000 Vaclav Slavik 
   8 // Licence:     wxWindows licence 
   9 ///////////////////////////////////////////////////////////////////////////// 
  14 #if defined(__GNUG__) && !defined(__APPLE__) 
  15 #pragma interface "xmlres.h" 
  19 #include "wx/string.h" 
  20 #include "wx/dynarray.h" 
  21 #include "wx/datetime.h" 
  23 #include "wx/gdicmn.h" 
  24 #include "wx/filesys.h" 
  25 #include "wx/bitmap.h" 
  27 #include "wx/artprov.h" 
  29 #include "wx/xml/xml.h" 
  31 #ifdef WXMAKINGDLL_XRC 
  32     #define WXDLLIMPEXP_XRC WXEXPORT 
  33 #elif defined(WXUSINGDLL) 
  34     #define WXDLLIMPEXP_XRC WXIMPORT 
  35 #else // not making nor using DLL 
  36     #define WXDLLIMPEXP_XRC 
  39 class WXDLLEXPORT wxMenu
; 
  40 class WXDLLEXPORT wxMenuBar
; 
  41 class WXDLLEXPORT wxDialog
; 
  42 class WXDLLEXPORT wxPanel
; 
  43 class WXDLLEXPORT wxWindow
; 
  44 class WXDLLEXPORT wxFrame
; 
  45 class WXDLLEXPORT wxToolBar
; 
  47 class WXDLLIMPEXP_XRC wxXmlResourceHandler
; 
  48 class WXDLLIMPEXP_XRC wxXmlSubclassFactory
; 
  49 class WXDLLIMPEXP_XRC wxXmlSubclassFactoriesList
; 
  50 class wxXmlResourceModule
; 
  53 // These macros indicate current version of XML resources (this information is 
  54 // encoded in root node of XRC file as "version" property). 
  56 // Rules for increasing version number: 
  57 //   - change it only if you made incompatible change to the format. Addition 
  58 //     of new attribute to control handler is _not_ incompatible change, because 
  59 //     older versions of the library may ignore it. 
  60 //   - if you change version number, follow these steps: 
  61 //       - set major, minor and release numbers to respective version numbers of 
  62 //         the wxWindows library (see wx/version.h) 
  63 //       - reset revision to 0 unless the first three are same as before, 
  64 //         in which case you should increase revision by one 
  65 #define WX_XMLRES_CURRENT_VERSION_MAJOR            2 
  66 #define WX_XMLRES_CURRENT_VERSION_MINOR            3 
  67 #define WX_XMLRES_CURRENT_VERSION_RELEASE          0 
  68 #define WX_XMLRES_CURRENT_VERSION_REVISION         1 
  69 #define WX_XMLRES_CURRENT_VERSION_STRING       _T("2.3.0.1") 
  71 #define WX_XMLRES_CURRENT_VERSION \ 
  72                 (WX_XMLRES_CURRENT_VERSION_MAJOR * 256*256*256 + \ 
  73                  WX_XMLRES_CURRENT_VERSION_MINOR * 256*256 + \ 
  74                  WX_XMLRES_CURRENT_VERSION_RELEASE * 256 + \ 
  75                  WX_XMLRES_CURRENT_VERSION_REVISION) 
  77 class WXDLLIMPEXP_XRC wxXmlResourceDataRecord
 
  80     wxXmlResourceDataRecord() : Doc(NULL
), Time(wxDateTime::Now()) {} 
  81     ~wxXmlResourceDataRecord() {delete Doc
;} 
  89 WX_DECLARE_USER_EXPORTED_OBJARRAY(wxXmlResourceDataRecord
, 
  90                                   wxXmlResourceDataRecords
, 
  93 enum wxXmlResourceFlags
 
  96     wxXRC_NO_SUBCLASSING 
= 2 
  99 // This class holds XML resources from one or more .xml files 
 100 // (or derived forms, either binary or zipped -- see manual for 
 102 class WXDLLIMPEXP_XRC wxXmlResource 
: public wxObject
 
 106     // Flags: wxXRC_USE_LOCALE 
 107     //              translatable strings will be translated via _() 
 108     //        wxXRC_NO_SUBCLASSING 
 109     //              subclass property of object nodes will be ignored 
 110     //              (useful for previews in XRC editors) 
 111     wxXmlResource(int flags 
= wxXRC_USE_LOCALE
); 
 114     // Flags: wxXRC_USE_LOCALE 
 115     //              translatable strings will be translated via _() 
 116     //        wxXRC_NO_SUBCLASSING 
 117     //              subclass property of object nodes will be ignored 
 118     //              (useful for previews in XRC editors) 
 119     wxXmlResource(const wxString
& filemask
, int flags 
= wxXRC_USE_LOCALE
); 
 124     // Loads resources from XML files that match given filemask. 
 125     // This method understands VFS (see filesys.h). 
 126     bool Load(const wxString
& filemask
); 
 128     // Initialize handlers for all supported controls/windows. This will 
 129     // make the executable quite big because it forces linking against 
 130     // most of the wxWindows library. 
 131     void InitAllHandlers(); 
 133     // Initialize only a specific handler (or custom handler). Convention says 
 134     // that handler name is equal to the control's name plus 'XmlHandler', for 
 135     // example wxTextCtrlXmlHandler, wxHtmlWindowXmlHandler. The XML resource 
 136     // compiler (xmlres) can create include file that contains initialization 
 137     // code for all controls used within the resource. 
 138     void AddHandler(wxXmlResourceHandler 
*handler
); 
 140     // Add a new handler at the begining of the handler list 
 141     void InsertHandler(wxXmlResourceHandler 
*handler
); 
 143     // Removes all handlers 
 144     void ClearHandlers(); 
 146     // Registers subclasses factory for use in XRC. This function is not meant 
 147     // for public use, please see the comment above wxXmlSubclassFactory 
 149     static void AddSubclassFactory(wxXmlSubclassFactory 
*factory
); 
 151     // Loads menu from resource. Returns NULL on failure. 
 152     wxMenu 
*LoadMenu(const wxString
& name
); 
 154     // Loads menubar from resource. Returns NULL on failure. 
 155     wxMenuBar 
*LoadMenuBar(wxWindow 
*parent
, const wxString
& name
); 
 157     // Loads menubar from resource. Returns NULL on failure. 
 158     wxMenuBar 
*LoadMenuBar(const wxString
& name
) { return LoadMenuBar(NULL
, name
); } 
 162     wxToolBar 
*LoadToolBar(wxWindow 
*parent
, const wxString
& name
); 
 165     // Loads a dialog. dlg points to parent window (if any). 
 166     wxDialog 
*LoadDialog(wxWindow 
*parent
, const wxString
& name
); 
 168     // Loads a dialog. dlg points to parent window (if any). This form 
 169     // is used to finish creation of already existing instance (main reason 
 170     // for this is that you may want to use derived class with new event table) 
 171     // Example (typical usage): 
 173     //      wxTheXmlResource->LoadDialog(&dlg, mainFrame, "my_dialog"); 
 175     bool LoadDialog(wxDialog 
*dlg
, wxWindow 
*parent
, const wxString
& name
); 
 177     // Loads a panel. panel points to parent window (if any). 
 178     wxPanel 
*LoadPanel(wxWindow 
*parent
, const wxString
& name
); 
 180     // Loads a panel. panel points to parent window (if any). This form 
 181     // is used to finish creation of already existing instance. 
 182     bool LoadPanel(wxPanel 
*panel
, wxWindow 
*parent
, const wxString
& name
); 
 185     wxFrame 
*LoadFrame(wxWindow
* parent
, const wxString
& name
); 
 186     bool LoadFrame(wxFrame
* frame
, wxWindow 
*parent
, const wxString
& name
); 
 188     // Load an object from the resource specifying both the resource name and 
 189     // the classname.  This lets you load nonstandard container windows. 
 190     wxObject 
*LoadObject(wxWindow 
*parent
, const wxString
& name
, 
 191                          const wxString
& classname
); 
 193     // Load an object from the resource specifying both the resource name and 
 194     // the classname.  This form lets you finish the creation of an existing 
 196     bool LoadObject(wxObject 
*instance
, wxWindow 
*parent
, const wxString
& name
, 
 197                     const wxString
& classname
); 
 199     // Loads a bitmap resource from a file. 
 200     wxBitmap 
LoadBitmap(const wxString
& name
); 
 202     // Loads an icon resource from a file. 
 203     wxIcon 
LoadIcon(const wxString
& name
); 
 205     // Attaches an unknown control to the given panel/window/dialog. 
 206     // Unknown controls are used in conjunction with <object class="unknown">. 
 207     bool AttachUnknownControl(const wxString
& name
, wxWindow 
*control
, 
 208                               wxWindow 
*parent 
= NULL
); 
 210     // Returns a numeric ID that is equivalent to the string id used in an XML 
 211     // resource. To be used in event tables. 
 212     // Macro XRCID is provided for convenience 
 213     static int GetXRCID(const wxChar 
*str_id
); 
 215     // Returns version information (a.b.c.d = d+ 256*c + 256^2*b + 256^3*a). 
 216     long GetVersion() const { return m_version
; } 
 218     // Compares resources version to argument. Returns -1 if resources version 
 219     // is less than the argument, +1 if greater and 0 if they equal. 
 220     int CompareVersion(int major
, int minor
, int release
, int revision
) const 
 221         { return GetVersion() - 
 222                  (major
*256*256*256 + minor
*256*256 + release
*256 + revision
); } 
 224 //// Singleton accessors. 
 226     // Gets the global resources object or creates one if none exists. 
 227     static wxXmlResource 
*Get(); 
 229     // Sets the global resources object and returns a pointer to the previous one (may be NULL). 
 230     static wxXmlResource 
*Set(wxXmlResource 
*res
); 
 232     // Returns flags, which may be a bitlist of wxXRC_USE_LOCALE and wxXRC_NO_SUBCLASSING. 
 233     int GetFlags() const { return m_flags
; } 
 234     // Set flags after construction. 
 235     void SetFlags(int flags
) { m_flags 
= flags
; } 
 238     // Scans the resources list for unloaded files and loads them. Also reloads 
 239     // files that have been modified since last loading. 
 240     void UpdateResources(); 
 242     // Finds a resource (calls UpdateResources) and returns a node containing it. 
 243     wxXmlNode 
*FindResource(const wxString
& name
, const wxString
& classname
, bool recursive 
= FALSE
); 
 245     // Helper function: finds a resource (calls UpdateResources) and returns a node containing it. 
 246     wxXmlNode 
*DoFindResource(wxXmlNode 
*parent
, const wxString
& name
, const wxString
& classname
, bool recursive
); 
 248     // Creates a resource from information in the given node 
 249     // (Uses only 'handlerToUse' if != NULL) 
 250     wxObject 
*CreateResFromNode(wxXmlNode 
*node
, wxObject 
*parent
, 
 251                                 wxObject 
*instance 
= NULL
, 
 252                                 wxXmlResourceHandler 
*handlerToUse 
= NULL
); 
 259     wxXmlResourceDataRecords m_data
; 
 261     wxFileSystem m_curFileSystem
; 
 262     wxFileSystem
& GetCurFileSystem() { return m_curFileSystem
; } 
 265     friend class wxXmlResourceHandler
; 
 266     friend class wxXmlResourceModule
; 
 268     static wxXmlSubclassFactoriesList 
*ms_subclassFactories
; 
 270     // singleton instance: 
 271     static wxXmlResource 
*ms_instance
; 
 275 // This macro translates string identifier (as used in XML resource, 
 276 // e.g. <menuitem id="my_menu">...</menuitem>) to integer id that is needed by 
 277 // wxWindows event tables. 
 279 //    BEGIN_EVENT_TABLE(MyFrame, wxFrame) 
 280 //       EVT_MENU(XRCID("quit"), MyFrame::OnQuit) 
 281 //       EVT_MENU(XRCID("about"), MyFrame::OnAbout) 
 282 //       EVT_MENU(XRCID("new"), MyFrame::OnNew) 
 283 //       EVT_MENU(XRCID("open"), MyFrame::OnOpen) 
 286 #define XRCID(str_id) \ 
 287     wxXmlResource::GetXRCID(wxT(str_id)) 
 290 // This macro returns pointer to particular control in dialog 
 291 // created using XML resources. You can use it to set/get values from 
 295 //    wxXmlResource::Get()->LoadDialog(&dlg, mainFrame, "my_dialog"); 
 296 //    XRCCTRL(dlg, "my_textctrl", wxTextCtrl)->SetValue(wxT("default value")); 
 299 #define XRCCTRL(window, id, type) \ 
 300     (wxDynamicCast((window).FindWindow(XRCID(id)), type)) 
 302 #define XRCCTRL(window, id, type) \ 
 303     ((type*)((window).FindWindow(XRCID(id)))) 
 306 // wxXmlResourceHandler is an abstract base class for resource handlers 
 307 // capable of creating a control from an XML node. 
 309 class WXDLLIMPEXP_XRC wxXmlResourceHandler 
: public wxObject
 
 311 DECLARE_ABSTRACT_CLASS(wxXmlResourceHandler
) 
 314     wxXmlResourceHandler(); 
 317     virtual ~wxXmlResourceHandler() {} 
 319     // Creates an object (menu, dialog, control, ...) from an XML node. 
 320     // Should check for validity. 
 321     // parent is a higher-level object (usually window, dialog or panel) 
 322     // that is often neccessary to create the resource. 
 323     // If instance is non-NULL it should not create a new instance via 'new' but 
 324     // should rather use this one, and call its Create method. 
 325     wxObject 
*CreateResource(wxXmlNode 
*node
, wxObject 
*parent
, 
 328     // This one is called from CreateResource after variables 
 330     virtual wxObject 
*DoCreateResource() = 0; 
 332     // Returns TRUE if it understands this node and can create 
 333     // a resource from it, FALSE otherwise. 
 334     virtual bool CanHandle(wxXmlNode 
*node
) = 0; 
 336     // Sets the parent resource. 
 337     void SetParentResource(wxXmlResource 
*res
) { m_resource 
= res
; } 
 340     wxXmlResource 
*m_resource
; 
 341     wxArrayString m_styleNames
; 
 342     wxArrayInt m_styleValues
; 
 344     // Variables (filled by CreateResource) 
 347     wxObject 
*m_parent
, *m_instance
; 
 348     wxWindow 
*m_parentAsWindow
, *m_instanceAsWindow
; 
 350     // --- Handy methods: 
 352     // Returns true if the node has a property class equal to classname, 
 353     // e.g. <object class="wxDialog">. 
 354     bool IsOfClass(wxXmlNode 
*node
, const wxString
& classname
) 
 355         { return node
->GetPropVal(wxT("class"), wxEmptyString
) == classname
; } 
 357     // Gets node content from wxXML_ENTITY_NODE 
 358     // The problem is, <tag>content<tag> is represented as 
 359     // wxXML_ENTITY_NODE name="tag", content="" 
 360     //    |-- wxXML_TEXT_NODE or 
 361     //        wxXML_CDATA_SECTION_NODE name="" content="content" 
 362     wxString 
GetNodeContent(wxXmlNode 
*node
); 
 364     // Check to see if a parameter exists. 
 365     bool HasParam(const wxString
& param
); 
 367     // Finds the node or returns NULL. 
 368     wxXmlNode 
*GetParamNode(const wxString
& param
); 
 370     // Finds the parameter value or returns the empty string. 
 371     wxString 
GetParamValue(const wxString
& param
); 
 373     // Add a style flag (e.g. wxMB_DOCKABLE) to the list of flags 
 374     // understood by this handler. 
 375     void AddStyle(const wxString
& name
, int value
); 
 377     // Add styles common to all wxWindow-derived classes. 
 378     void AddWindowStyles(); 
 380     // Gets style flags from text in form "flag | flag2| flag3 |..." 
 381     // Only understads flags added with AddStyle 
 382     int GetStyle(const wxString
& param 
= wxT("style"), int defaults 
= 0); 
 384     // Gets text from param and does some conversions: 
 385     // - replaces \n, \r, \t by respective chars (according to C syntax) 
 386     // - replaces _ by & and __ by _ (needed for _File => &File because of XML) 
 387     // - calls wxGetTranslations (unless disabled in wxXmlResource) 
 388     wxString 
GetText(const wxString
& param
, bool translate 
= TRUE
); 
 390     // Returns the XRCID. 
 393     // Returns the resource name. 
 396     // Gets a bool flag (1, t, yes, on, true are TRUE, everything else is FALSE). 
 397     bool GetBool(const wxString
& param
, bool defaultv 
= FALSE
); 
 399     // Gets the integer value from the parameter. 
 400     long GetLong( const wxString
& param
, long defaultv 
= 0 ); 
 402     // Gets colour in HTML syntax (#RRGGBB). 
 403     wxColour 
GetColour(const wxString
& param
); 
 405     // Gets the size (may be in dialog units). 
 406     wxSize 
GetSize(const wxString
& param 
= wxT("size")); 
 408     // Gets the position (may be in dialog units). 
 409     wxPoint 
GetPosition(const wxString
& param 
= wxT("pos")); 
 411     // Gets a dimension (may be in dialog units). 
 412     wxCoord 
GetDimension(const wxString
& param
, wxCoord defaultv 
= 0); 
 415     wxBitmap 
GetBitmap(const wxString
& param 
= wxT("bitmap"), 
 416                        const wxArtClient
& defaultArtClient 
= wxART_OTHER
, 
 417                        wxSize size 
= wxDefaultSize
); 
 420     wxIcon 
GetIcon(const wxString
& param 
= wxT("icon"), 
 421                    const wxArtClient
& defaultArtClient 
= wxART_OTHER
, 
 422                    wxSize size 
= wxDefaultSize
); 
 425     wxFont 
GetFont(const wxString
& param 
= wxT("font")); 
 427     // Sets common window options. 
 428     void SetupWindow(wxWindow 
*wnd
); 
 431     void CreateChildren(wxObject 
*parent
, bool this_hnd_only 
= FALSE
); 
 434     void CreateChildrenPrivately(wxObject 
*parent
, wxXmlNode 
*rootnode 
= NULL
); 
 436     // Creates a resource from a node. 
 437     wxObject 
*CreateResFromNode(wxXmlNode 
*node
, 
 438                                 wxObject 
*parent
, wxObject 
*instance 
= NULL
) 
 439         { return m_resource
->CreateResFromNode(node
, parent
, instance
); } 
 443     wxFileSystem
& GetCurFileSystem() { return m_resource
->GetCurFileSystem(); } 
 448 // Programmer-friendly macros for writing XRC handlers: 
 450 #define XRC_ADD_STYLE(style) AddStyle(wxT(#style), style) 
 452 #define XRC_MAKE_INSTANCE(variable, classname) \ 
 453    classname *variable = NULL; \ 
 455        variable = wxStaticCast(m_instance, classname); \ 
 457        variable = new classname; 
 460 // FIXME -- remove this $%^#$%#$@# as soon as Ron checks his changes in!! 
 461 void wxXmlInitResourceModule(); 
 464 // This class is used to create instances of XRC "object" nodes with "subclass" 
 465 // property. It is _not_ supposed to be used by XRC users, you should instead 
 466 // register your subclasses via wxWindows' RTTI mechanism. This class is useful 
 467 // only for language bindings developer who need a way to implement subclassing 
 468 // in wxWindows ports that don't support wxRTTI (e.g. wxPython). 
 469 class WXDLLIMPEXP_XRC wxXmlSubclassFactory
 
 472     // Try to create instance of given class and return it, return NULL on 
 474     virtual wxObject 
*Create(const wxString
& className
) = 0; 
 475     virtual ~wxXmlSubclassFactory() {} 
 479 /* ------------------------------------------------------------------------- 
 480    Backward compatibility macros. Do *NOT* use, they may disappear in future 
 481    versions of the XRC library! 
 482    ------------------------------------------------------------------------- */ 
 483 #if WXWIN_COMPATIBILITY_2_4 
 484     #define ADD_STYLE         XRC_ADD_STYLE 
 485     #define wxTheXmlResource  wxXmlResource::Get() 
 487     #define XMLCTRL           XRCCTRL 
 488     #define GetXMLID          GetXRCID 
 492 #endif // _WX_XMLRES_H_