]> git.saurik.com Git - wxWidgets.git/blame - src/xrc/xmlres.cpp
better native types for carbon
[wxWidgets.git] / src / xrc / xmlres.cpp
CommitLineData
78d14f80 1/////////////////////////////////////////////////////////////////////////////
88a7a4e1 2// Name: src/xrc/xmlres.cpp
b5d6954b 3// Purpose: XRC resources
78d14f80
VS
4// Author: Vaclav Slavik
5// Created: 2000/03/05
6// RCS-ID: $Id$
7// Copyright: (c) 2000 Vaclav Slavik
8// Licence: wxWindows licence
9/////////////////////////////////////////////////////////////////////////////
10
78d14f80
VS
11// For compilers that support precompilation, includes "wx.h".
12#include "wx/wxprec.h"
13
14#ifdef __BORLANDC__
15 #pragma hdrstop
16#endif
17
621be1ec 18#if wxUSE_XRC
a1e4ec87 19
88a7a4e1
WS
20#include "wx/xrc/xmlres.h"
21
22#ifndef WX_PRECOMP
23 #include "wx/intl.h"
e4db172a 24 #include "wx/log.h"
8e609c82 25 #include "wx/panel.h"
76b49cf4 26 #include "wx/frame.h"
fdf565fe 27 #include "wx/dialog.h"
9eddec69 28 #include "wx/settings.h"
0bca0373 29 #include "wx/bitmap.h"
155ecd4c 30 #include "wx/image.h"
02761f6c 31 #include "wx/module.h"
193d0c93 32 #include "wx/wxcrtvararg.h"
88a7a4e1
WS
33#endif
34
e7a3a5a5 35#ifndef __WXWINCE__
88a7a4e1 36 #include <locale.h>
e7a3a5a5 37#endif
1df61962 38
eb2d0d23 39#include "wx/vector.h"
78d14f80
VS
40#include "wx/wfstream.h"
41#include "wx/filesys.h"
317a0d73 42#include "wx/filename.h"
78d14f80
VS
43#include "wx/tokenzr.h"
44#include "wx/fontenum.h"
78d14f80 45#include "wx/fontmap.h"
af1337b0 46#include "wx/artprov.h"
2bb9a404 47#include "wx/dir.h"
34c6bbee 48#include "wx/xml/xml.h"
78d14f80 49
f35fdf7e 50
eb2d0d23
VS
51class wxXmlResourceDataRecord
52{
53public:
54 wxXmlResourceDataRecord() : Doc(NULL) {
55#if wxUSE_DATETIME
56 Time = wxDateTime::Now();
57#endif
58 }
59 ~wxXmlResourceDataRecord() {delete Doc;}
60
61 wxString File;
62 wxXmlDocument *Doc;
63#if wxUSE_DATETIME
64 wxDateTime Time;
65#endif
66};
67
f396e5a7 68class wxXmlResourceDataRecords : public wxVector<wxXmlResourceDataRecord*>
eb2d0d23
VS
69{
70 // this is a class so that it can be forward-declared
71};
78d14f80 72
23239d94
VZ
73namespace
74{
75
76// helper used by DoFindResource() and elsewhere: returns true if this is an
77// object or object_ref node
78//
79// node must be non-NULL
80inline bool IsObjectNode(wxXmlNode *node)
81{
82 return node->GetType() == wxXML_ELEMENT_NODE &&
83 (node->GetName() == wxS("object") ||
84 node->GetName() == wxS("object_ref"));
85}
86
87} // anonymous namespace
88
78d14f80 89
824e8eaa
VS
90wxXmlResource *wxXmlResource::ms_instance = NULL;
91
92/*static*/ wxXmlResource *wxXmlResource::Get()
93{
94 if ( !ms_instance )
95 ms_instance = new wxXmlResource;
96 return ms_instance;
97}
98
99/*static*/ wxXmlResource *wxXmlResource::Set(wxXmlResource *res)
100{
101 wxXmlResource *old = ms_instance;
102 ms_instance = res;
103 return old;
104}
105
d4a724d4 106wxXmlResource::wxXmlResource(int flags, const wxString& domain)
78d14f80 107{
daa85ee3 108 m_flags = flags;
78d14f80 109 m_version = -1;
eb2d0d23 110 m_data = new wxXmlResourceDataRecords;
d7a80cf5 111 SetDomain(domain);
78d14f80
VS
112}
113
d4a724d4 114wxXmlResource::wxXmlResource(const wxString& filemask, int flags, const wxString& domain)
78d14f80 115{
daa85ee3 116 m_flags = flags;
78d14f80 117 m_version = -1;
eb2d0d23 118 m_data = new wxXmlResourceDataRecords;
d7a80cf5 119 SetDomain(domain);
78d14f80
VS
120 Load(filemask);
121}
122
123wxXmlResource::~wxXmlResource()
124{
125 ClearHandlers();
eb2d0d23 126
f396e5a7
VS
127 for ( wxXmlResourceDataRecords::iterator i = m_data->begin();
128 i != m_data->end(); ++i )
129 {
130 delete *i;
131 }
eb2d0d23 132 delete m_data;
78d14f80
VS
133}
134
d7a80cf5 135void wxXmlResource::SetDomain(const wxString& domain)
d4a724d4 136{
d7a80cf5 137 m_domain = domain;
d4a724d4
RD
138}
139
78d14f80 140
60fd818a
VZ
141/* static */
142wxString wxXmlResource::ConvertFileNameToURL(const wxString& filename)
143{
144 wxString fnd(filename);
145
146 // NB: as Load() and Unload() accept both filenames and URLs (should
147 // probably be changed to filenames only, but embedded resources
148 // currently rely on its ability to handle URLs - FIXME) we need to
149 // determine whether found name is filename and not URL and this is the
150 // fastest/simplest way to do it
151 if (wxFileName::FileExists(fnd))
152 {
153 // Make the name absolute filename, because the app may
154 // change working directory later:
155 wxFileName fn(fnd);
156 if (fn.IsRelative())
157 {
158 fn.MakeAbsolute();
159 fnd = fn.GetFullPath();
160 }
161#if wxUSE_FILESYSTEM
162 fnd = wxFileSystem::FileNameToURL(fnd);
163#endif
164 }
165
166 return fnd;
167}
168
169#if wxUSE_FILESYSTEM
170
171/* static */
172bool wxXmlResource::IsArchive(const wxString& filename)
173{
174 const wxString fnd = filename.Lower();
175
176 return fnd.Matches(wxT("*.zip")) || fnd.Matches(wxT("*.xrs"));
177}
178
179#endif // wxUSE_FILESYSTEM
180
04ae32cd
VS
181bool wxXmlResource::LoadFile(const wxFileName& file)
182{
159852ae 183#if wxUSE_FILESYSTEM
04ae32cd 184 return Load(wxFileSystem::FileNameToURL(file));
159852ae
VS
185#else
186 return Load(file.GetFullPath());
187#endif
04ae32cd
VS
188}
189
2bb9a404
VS
190bool wxXmlResource::LoadAllFiles(const wxString& dirname)
191{
192 bool ok = true;
193 wxArrayString files;
194
195 wxDir::GetAllFiles(dirname, &files, "*.xrc");
196
197 for ( wxArrayString::const_iterator i = files.begin(); i != files.end(); ++i )
198 {
199 if ( !LoadFile(*i) )
200 ok = false;
201 }
202
203 return ok;
204}
205
acd32ffc 206bool wxXmlResource::Load(const wxString& filemask_)
78d14f80 207{
acd32ffc
VS
208 wxString filemask = ConvertFileNameToURL(filemask_);
209
78d14f80
VS
210#if wxUSE_FILESYSTEM
211 wxFileSystem fsys;
212# define wxXmlFindFirst fsys.FindFirst(filemask, wxFILE)
213# define wxXmlFindNext fsys.FindNext()
214#else
215# define wxXmlFindFirst wxFindFirstFile(filemask, wxFILE)
216# define wxXmlFindNext wxFindNextFile()
217#endif
e5bb501b
VZ
218 wxString fnd = wxXmlFindFirst;
219 if ( fnd.empty() )
220 {
221 wxLogError(_("Cannot load resources from '%s'."), filemask);
222 return false;
223 }
224
ec157c8f 225 while (!fnd.empty())
78d14f80
VS
226 {
227#if wxUSE_FILESYSTEM
60fd818a 228 if ( IsArchive(fnd) )
78d14f80 229 {
e5bb501b
VZ
230 if ( !Load(fnd + wxT("#zip:*.xrc")) )
231 return false;
78d14f80 232 }
60fd818a
VZ
233 else // a single resource URL
234#endif // wxUSE_FILESYSTEM
78d14f80 235 {
f396e5a7
VS
236 wxXmlResourceDataRecord *drec = new wxXmlResourceDataRecord;
237 drec->File = fnd;
eb2d0d23 238 Data().push_back(drec);
78d14f80
VS
239 }
240
e5bb501b 241 fnd = wxXmlFindNext;
78d14f80
VS
242 }
243# undef wxXmlFindFirst
244# undef wxXmlFindNext
e5bb501b
VZ
245
246 return UpdateResources();
78d14f80
VS
247}
248
60fd818a
VZ
249bool wxXmlResource::Unload(const wxString& filename)
250{
251 wxASSERT_MSG( !wxIsWild(filename),
252 _T("wildcards not supported by wxXmlResource::Unload()") );
253
254 wxString fnd = ConvertFileNameToURL(filename);
255#if wxUSE_FILESYSTEM
256 const bool isArchive = IsArchive(fnd);
257 if ( isArchive )
258 fnd += _T("#zip:");
259#endif // wxUSE_FILESYSTEM
260
261 bool unloaded = false;
eb2d0d23
VS
262 for ( wxXmlResourceDataRecords::iterator i = Data().begin();
263 i != Data().end(); ++i )
60fd818a
VZ
264 {
265#if wxUSE_FILESYSTEM
266 if ( isArchive )
267 {
f396e5a7 268 if ( (*i)->File.StartsWith(fnd) )
60fd818a
VZ
269 unloaded = true;
270 // don't break from the loop, we can have other matching files
271 }
272 else // a single resource URL
273#endif // wxUSE_FILESYSTEM
274 {
f396e5a7 275 if ( (*i)->File == fnd )
60fd818a 276 {
f8b1df0b 277 delete *i;
eb2d0d23 278 Data().erase(i);
60fd818a
VZ
279 unloaded = true;
280
281 // no sense in continuing, there is only one file with this URL
282 break;
283 }
284 }
285 }
286
287 return unloaded;
288}
289
78d14f80 290
854e189f 291IMPLEMENT_ABSTRACT_CLASS(wxXmlResourceHandler, wxObject)
78d14f80
VS
292
293void wxXmlResource::AddHandler(wxXmlResourceHandler *handler)
294{
eb2d0d23 295 m_handlers.push_back(handler);
78d14f80
VS
296 handler->SetParentResource(this);
297}
298
92e898b0
RD
299void wxXmlResource::InsertHandler(wxXmlResourceHandler *handler)
300{
eb2d0d23 301 m_handlers.insert(m_handlers.begin(), handler);
92e898b0
RD
302 handler->SetParentResource(this);
303}
304
78d14f80
VS
305
306
307void wxXmlResource::ClearHandlers()
308{
eb2d0d23
VS
309 for ( wxVector<wxXmlResourceHandler*>::iterator i = m_handlers.begin();
310 i != m_handlers.end(); ++i )
311 delete *i;
312 m_handlers.clear();
78d14f80
VS
313}
314
315
78d14f80
VS
316wxMenu *wxXmlResource::LoadMenu(const wxString& name)
317{
318 return (wxMenu*)CreateResFromNode(FindResource(name, wxT("wxMenu")), NULL, NULL);
319}
320
321
322
4a1b9596 323wxMenuBar *wxXmlResource::LoadMenuBar(wxWindow *parent, const wxString& name)
78d14f80 324{
4a1b9596 325 return (wxMenuBar*)CreateResFromNode(FindResource(name, wxT("wxMenuBar")), parent, NULL);
78d14f80
VS
326}
327
328
329
4a1b9596 330#if wxUSE_TOOLBAR
78d14f80
VS
331wxToolBar *wxXmlResource::LoadToolBar(wxWindow *parent, const wxString& name)
332{
333 return (wxToolBar*)CreateResFromNode(FindResource(name, wxT("wxToolBar")), parent, NULL);
334}
4a1b9596 335#endif
78d14f80
VS
336
337
338wxDialog *wxXmlResource::LoadDialog(wxWindow *parent, const wxString& name)
339{
4dd75a6a 340 return (wxDialog*)CreateResFromNode(FindResource(name, wxT("wxDialog")), parent, NULL);
78d14f80
VS
341}
342
343bool wxXmlResource::LoadDialog(wxDialog *dlg, wxWindow *parent, const wxString& name)
344{
345 return CreateResFromNode(FindResource(name, wxT("wxDialog")), parent, dlg) != NULL;
346}
347
348
349
350wxPanel *wxXmlResource::LoadPanel(wxWindow *parent, const wxString& name)
351{
352 return (wxPanel*)CreateResFromNode(FindResource(name, wxT("wxPanel")), parent, NULL);
353}
354
355bool wxXmlResource::LoadPanel(wxPanel *panel, wxWindow *parent, const wxString& name)
356{
357 return CreateResFromNode(FindResource(name, wxT("wxPanel")), parent, panel) != NULL;
358}
359
92e898b0
RD
360wxFrame *wxXmlResource::LoadFrame(wxWindow* parent, const wxString& name)
361{
362 return (wxFrame*)CreateResFromNode(FindResource(name, wxT("wxFrame")), parent, NULL);
363}
364
78d14f80
VS
365bool wxXmlResource::LoadFrame(wxFrame* frame, wxWindow *parent, const wxString& name)
366{
367 return CreateResFromNode(FindResource(name, wxT("wxFrame")), parent, frame) != NULL;
368}
369
370wxBitmap wxXmlResource::LoadBitmap(const wxString& name)
371{
372 wxBitmap *bmp = (wxBitmap*)CreateResFromNode(
373 FindResource(name, wxT("wxBitmap")), NULL, NULL);
374 wxBitmap rt;
375
376 if (bmp) { rt = *bmp; delete bmp; }
377 return rt;
378}
379
380wxIcon wxXmlResource::LoadIcon(const wxString& name)
381{
382 wxIcon *icon = (wxIcon*)CreateResFromNode(
383 FindResource(name, wxT("wxIcon")), NULL, NULL);
384 wxIcon rt;
385
386 if (icon) { rt = *icon; delete icon; }
387 return rt;
388}
389
92e898b0
RD
390
391wxObject *wxXmlResource::LoadObject(wxWindow *parent, const wxString& name, const wxString& classname)
392{
393 return CreateResFromNode(FindResource(name, classname), parent, NULL);
394}
395
396bool wxXmlResource::LoadObject(wxObject *instance, wxWindow *parent, const wxString& name, const wxString& classname)
397{
398 return CreateResFromNode(FindResource(name, classname), parent, instance) != NULL;
399}
400
401
78d14f80
VS
402bool wxXmlResource::AttachUnknownControl(const wxString& name,
403 wxWindow *control, wxWindow *parent)
404{
405 if (parent == NULL)
406 parent = control->GetParent();
407 wxWindow *container = parent->FindWindow(name + wxT("_container"));
408 if (!container)
409 {
819559b2 410 wxLogError("Cannot find container for unknown control '%s'.", name);
f80ea77b 411 return false;
78d14f80
VS
412 }
413 return control->Reparent(container);
414}
415
416
77b2f9b1 417static void ProcessPlatformProperty(wxXmlNode *node)
78d14f80
VS
418{
419 wxString s;
420 bool isok;
421
422 wxXmlNode *c = node->GetChildren();
423 while (c)
424 {
f80ea77b 425 isok = false;
288b6107 426 if (!c->GetAttribute(wxT("platform"), &s))
f80ea77b 427 isok = true;
78d14f80
VS
428 else
429 {
2b5f62a0 430 wxStringTokenizer tkn(s, wxT(" |"));
78d14f80
VS
431
432 while (tkn.HasMoreTokens())
433 {
434 s = tkn.GetNextToken();
84389518 435#ifdef __WINDOWS__
d003330c
VS
436 if (s == wxT("win")) isok = true;
437#endif
b380439d 438#if defined(__MAC__) || defined(__APPLE__)
d003330c 439 if (s == wxT("mac")) isok = true;
b380439d
RD
440#elif defined(__UNIX__)
441 if (s == wxT("unix")) isok = true;
78d14f80 442#endif
d003330c
VS
443#ifdef __OS2__
444 if (s == wxT("os2")) isok = true;
445#endif
446
447 if (isok)
448 break;
78d14f80
VS
449 }
450 }
451
452 if (isok)
d7b1d73c 453 {
78d14f80 454 ProcessPlatformProperty(c);
d7b1d73c
VS
455 c = c->GetNext();
456 }
78d14f80
VS
457 else
458 {
d7b1d73c 459 wxXmlNode *c2 = c->GetNext();
db59a97c 460 node->RemoveChild(c);
78d14f80 461 delete c;
d7b1d73c 462 c = c2;
78d14f80 463 }
78d14f80
VS
464 }
465}
466
467
468
d614f51b 469bool wxXmlResource::UpdateResources()
78d14f80 470{
d614f51b 471 bool rt = true;
78d14f80
VS
472 bool modif;
473# if wxUSE_FILESYSTEM
474 wxFSFile *file = NULL;
19d0f58d 475 wxUnusedVar(file);
78d14f80
VS
476 wxFileSystem fsys;
477# endif
478
480505bc
VS
479 wxString encoding(wxT("UTF-8"));
480#if !wxUSE_UNICODE && wxUSE_INTL
481 if ( (GetFlags() & wxXRC_USE_LOCALE) == 0 )
482 {
75d38380
VS
483 // In case we are not using wxLocale to translate strings, convert the
484 // strings GUI's charset. This must not be done when wxXRC_USE_LOCALE
485 // is on, because it could break wxGetTranslation lookup.
480505bc
VS
486 encoding = wxLocale::GetSystemEncodingName();
487 }
488#endif
489
eb2d0d23
VS
490 for ( wxXmlResourceDataRecords::iterator i = Data().begin();
491 i != Data().end(); ++i )
78d14f80 492 {
f396e5a7
VS
493 wxXmlResourceDataRecord* const rec = *i;
494
495 modif = (rec->Doc == NULL);
78d14f80 496
648db587 497 if (!modif && !(m_flags & wxXRC_NO_RELOADING))
78d14f80
VS
498 {
499# if wxUSE_FILESYSTEM
f396e5a7 500 file = fsys.OpenFile(rec->File);
34af0de4 501# if wxUSE_DATETIME
f396e5a7 502 modif = file && file->GetModificationTime() > rec->Time;
34af0de4
VZ
503# else // wxUSE_DATETIME
504 modif = true;
505# endif // wxUSE_DATETIME
78d14f80 506 if (!file)
d614f51b 507 {
f396e5a7 508 wxLogError(_("Cannot open file '%s'."), rec->File);
d614f51b
VS
509 rt = false;
510 }
78d14f80 511 wxDELETE(file);
19d0f58d 512 wxUnusedVar(file);
34af0de4
VZ
513# else // wxUSE_FILESYSTEM
514# if wxUSE_DATETIME
f396e5a7 515 modif = wxDateTime(wxFileModificationTime(rec->File)) > rec->Time;
34af0de4
VZ
516# else // wxUSE_DATETIME
517 modif = true;
518# endif // wxUSE_DATETIME
519# endif // wxUSE_FILESYSTEM
78d14f80
VS
520 }
521
522 if (modif)
523 {
f396e5a7 524 wxLogTrace(_T("xrc"), _T("opening file '%s'"), rec->File);
648db587 525
480505bc 526 wxInputStream *stream = NULL;
78d14f80
VS
527
528# if wxUSE_FILESYSTEM
f396e5a7 529 file = fsys.OpenFile(rec->File);
f80ea77b
WS
530 if (file)
531 stream = file->GetStream();
78d14f80 532# else
f396e5a7 533 stream = new wxFileInputStream(rec->File);
78d14f80
VS
534# endif
535
536 if (stream)
537 {
f396e5a7
VS
538 delete rec->Doc;
539 rec->Doc = new wxXmlDocument;
78d14f80 540 }
9690b006 541 if (!stream || !stream->IsOk() || !rec->Doc->Load(*stream, encoding))
78d14f80 542 {
480505bc 543 wxLogError(_("Cannot load resources from file '%s'."),
f396e5a7
VS
544 rec->File);
545 wxDELETE(rec->Doc);
d614f51b 546 rt = false;
78d14f80 547 }
f396e5a7 548 else if (rec->Doc->GetRoot()->GetName() != wxT("resource"))
78d14f80 549 {
819559b2
VS
550 ReportError
551 (
552 rec->Doc->GetRoot(),
553 "invalid XRC resource, doesn't have root node <resource>"
554 );
f396e5a7 555 wxDELETE(rec->Doc);
d614f51b 556 rt = false;
78d14f80
VS
557 }
558 else
f80ea77b 559 {
78d14f80
VS
560 long version;
561 int v1, v2, v3, v4;
f396e5a7 562 wxString verstr = rec->Doc->GetRoot()->GetAttribute(
78d14f80
VS
563 wxT("version"), wxT("0.0.0.0"));
564 if (wxSscanf(verstr.c_str(), wxT("%i.%i.%i.%i"),
565 &v1, &v2, &v3, &v4) == 4)
566 version = v1*256*256*256+v2*256*256+v3*256+v4;
567 else
568 version = 0;
569 if (m_version == -1)
570 m_version = version;
571 if (m_version != version)
d614f51b 572 {
819559b2 573 wxLogError("Resource files must have same version number.");
d614f51b
VS
574 rt = false;
575 }
78d14f80 576
f396e5a7 577 ProcessPlatformProperty(rec->Doc->GetRoot());
34af0de4 578#if wxUSE_DATETIME
496f0a58 579#if wxUSE_FILESYSTEM
f396e5a7 580 rec->Time = file->GetModificationTime();
34af0de4 581#else // wxUSE_FILESYSTEM
f396e5a7 582 rec->Time = wxDateTime(wxFileModificationTime(rec->File));
34af0de4
VZ
583#endif // wxUSE_FILESYSTEM
584#endif // wxUSE_DATETIME
f80ea77b 585 }
78d14f80
VS
586
587# if wxUSE_FILESYSTEM
f80ea77b
WS
588 wxDELETE(file);
589 wxUnusedVar(file);
78d14f80 590# else
f80ea77b 591 wxDELETE(stream);
78d14f80
VS
592# endif
593 }
594 }
d614f51b
VS
595
596 return rt;
78d14f80
VS
597}
598
b272b6dc
RD
599wxXmlNode *wxXmlResource::DoFindResource(wxXmlNode *parent,
600 const wxString& name,
601 const wxString& classname,
23239d94 602 bool recursive) const
47793ab8 603{
47793ab8
VS
604 wxXmlNode *node;
605
606 // first search for match at the top-level nodes (as this is
607 // where the resource is most commonly looked for):
608 for (node = parent->GetChildren(); node; node = node->GetNext())
609 {
23239d94 610 if ( IsObjectNode(node) && node->GetAttribute(wxS("name")) == name )
2b5f62a0 611 {
23239d94
VZ
612 // empty class name matches everything
613 if ( classname.empty() )
2b5f62a0 614 return node;
23239d94
VZ
615
616 wxString cls(node->GetAttribute(wxS("class")));
617
288b6107 618 // object_ref may not have 'class' attribute:
23239d94 619 if (cls.empty() && node->GetName() == wxS("object_ref"))
2b5f62a0 620 {
23239d94 621 wxString refName = node->GetAttribute(wxS("ref"));
2b5f62a0
VZ
622 if (refName.empty())
623 continue;
23239d94
VZ
624
625 const wxXmlNode * const refNode = GetResourceNode(refName);
626 if ( refNode )
627 cls = refNode->GetAttribute(wxS("class"));
2b5f62a0 628 }
23239d94
VZ
629
630 if ( cls == classname )
631 return node;
2b5f62a0 632 }
47793ab8
VS
633 }
634
23239d94 635 // then recurse in child nodes
47793ab8 636 if ( recursive )
23239d94 637 {
47793ab8
VS
638 for (node = parent->GetChildren(); node; node = node->GetNext())
639 {
23239d94 640 if ( IsObjectNode(node) )
47793ab8 641 {
f80ea77b 642 wxXmlNode* found = DoFindResource(node, name, classname, true);
47793ab8
VS
643 if ( found )
644 return found;
645 }
646 }
23239d94 647 }
47793ab8 648
23239d94 649 return NULL;
47793ab8 650}
78d14f80 651
b272b6dc 652wxXmlNode *wxXmlResource::FindResource(const wxString& name,
47793ab8
VS
653 const wxString& classname,
654 bool recursive)
78d14f80 655{
23239d94
VZ
656 wxString path;
657 wxXmlNode * const
658 node = GetResourceNodeAndLocation(name, classname, recursive, &path);
659
660 if ( !node )
661 {
819559b2
VS
662 ReportError
663 (
664 NULL,
665 wxString::Format
666 (
667 "XRC resource \"%s\" (class \"%s\") not found",
668 name, classname
669 )
670 );
23239d94
VZ
671 }
672#if wxUSE_FILESYSTEM
673 else // node was found
674 {
675 // ensure that relative paths work correctly when loading this node
676 // (which should happen as soon as we return as FindResource() result
677 // is always passed to CreateResFromNode())
678 m_curFileSystem.ChangePathTo(path);
679 }
680#endif // wxUSE_FILESYSTEM
681
682 return node;
683}
684
685wxXmlNode *
686wxXmlResource::GetResourceNodeAndLocation(const wxString& name,
687 const wxString& classname,
688 bool recursive,
689 wxString *path) const
690{
691 // ensure everything is up-to-date: this is needed to support on-remand
692 // reloading of XRC files
693 const_cast<wxXmlResource *>(this)->UpdateResources();
78d14f80 694
eb2d0d23
VS
695 for ( wxXmlResourceDataRecords::const_iterator f = Data().begin();
696 f != Data().end(); ++f )
78d14f80 697 {
23239d94
VZ
698 wxXmlResourceDataRecord *const rec = *f;
699 wxXmlDocument * const doc = rec->Doc;
700 if ( !doc || !doc->GetRoot() )
47793ab8
VS
701 continue;
702
23239d94
VZ
703 wxXmlNode * const
704 found = DoFindResource(doc->GetRoot(), name, classname, recursive);
47793ab8
VS
705 if ( found )
706 {
23239d94
VZ
707 if ( path )
708 *path = rec->File;
709
47793ab8
VS
710 return found;
711 }
78d14f80
VS
712 }
713
78d14f80
VS
714 return NULL;
715}
716
47793ab8
VS
717static void MergeNodes(wxXmlNode& dest, wxXmlNode& with)
718{
288b6107
VS
719 // Merge attributes:
720 for ( wxXmlAttribute *attr = with.GetAttributes();
721 attr; attr = attr->GetNext() )
47793ab8 722 {
288b6107
VS
723 wxXmlAttribute *dattr;
724 for (dattr = dest.GetAttributes(); dattr; dattr = dattr->GetNext())
47793ab8 725 {
b272b6dc 726
288b6107 727 if ( dattr->GetName() == attr->GetName() )
47793ab8 728 {
288b6107 729 dattr->SetValue(attr->GetValue());
47793ab8
VS
730 break;
731 }
732 }
78d14f80 733
288b6107
VS
734 if ( !dattr )
735 dest.AddAttribute(attr->GetName(), attr->GetValue());
47793ab8
VS
736 }
737
738 // Merge child nodes:
739 for (wxXmlNode* node = with.GetChildren(); node; node = node->GetNext())
740 {
288b6107 741 wxString name = node->GetAttribute(wxT("name"), wxEmptyString);
47793ab8
VS
742 wxXmlNode *dnode;
743
744 for (dnode = dest.GetChildren(); dnode; dnode = dnode->GetNext() )
745 {
746 if ( dnode->GetName() == node->GetName() &&
288b6107 747 dnode->GetAttribute(wxT("name"), wxEmptyString) == name &&
47793ab8
VS
748 dnode->GetType() == node->GetType() )
749 {
750 MergeNodes(*dnode, *node);
751 break;
752 }
753 }
754
755 if ( !dnode )
b26a650c
VZ
756 {
757 static const wxChar *AT_END = wxT("end");
288b6107 758 wxString insert_pos = node->GetAttribute(wxT("insert_at"), AT_END);
b26a650c
VZ
759 if ( insert_pos == AT_END )
760 {
761 dest.AddChild(new wxXmlNode(*node));
762 }
763 else if ( insert_pos == wxT("begin") )
764 {
765 dest.InsertChild(new wxXmlNode(*node), dest.GetChildren());
766 }
767 }
47793ab8
VS
768 }
769
0bca0373 770 if ( dest.GetType() == wxXML_TEXT_NODE && with.GetContent().length() )
47793ab8
VS
771 dest.SetContent(with.GetContent());
772}
78d14f80 773
317a0d73
VS
774wxObject *wxXmlResource::CreateResFromNode(wxXmlNode *node, wxObject *parent,
775 wxObject *instance,
776 wxXmlResourceHandler *handlerToUse)
78d14f80
VS
777{
778 if (node == NULL) return NULL;
779
47793ab8
VS
780 // handling of referenced resource
781 if ( node->GetName() == wxT("object_ref") )
782 {
288b6107 783 wxString refName = node->GetAttribute(wxT("ref"), wxEmptyString);
f80ea77b 784 wxXmlNode* refNode = FindResource(refName, wxEmptyString, true);
47793ab8
VS
785
786 if ( !refNode )
787 {
819559b2
VS
788 ReportError
789 (
790 node,
791 wxString::Format
792 (
793 "referenced object node with ref=\"%s\" not found",
794 refName
795 )
796 );
47793ab8
VS
797 return NULL;
798 }
799
800 wxXmlNode copy(*refNode);
801 MergeNodes(copy, *node);
802
803 return CreateResFromNode(&copy, parent, instance);
804 }
805
317a0d73 806 if (handlerToUse)
b380439d 807 {
317a0d73 808 if (handlerToUse->CanHandle(node))
8e8a4e85 809 {
317a0d73 810 return handlerToUse->CreateResource(node, parent, instance);
8e8a4e85 811 }
317a0d73
VS
812 }
813 else if (node->GetName() == wxT("object"))
b380439d 814 {
eb2d0d23
VS
815 for ( wxVector<wxXmlResourceHandler*>::iterator h = m_handlers.begin();
816 h != m_handlers.end(); ++h )
317a0d73 817 {
eb2d0d23 818 wxXmlResourceHandler *handler = *h;
317a0d73 819 if (handler->CanHandle(node))
317a0d73 820 return handler->CreateResource(node, parent, instance);
78d14f80 821 }
78d14f80
VS
822 }
823
819559b2
VS
824 ReportError
825 (
826 node,
827 wxString::Format
828 (
829 "no handler found for XML node \"%s\" (class \"%s\")",
830 node->GetName(),
831 node->GetAttribute("class", wxEmptyString)
832 )
833 );
78d14f80
VS
834 return NULL;
835}
836
837
eb2d0d23
VS
838class wxXmlSubclassFactories : public wxVector<wxXmlSubclassFactory*>
839{
840 // this is a class so that it can be forward-declared
841};
2b5f62a0 842
eb2d0d23 843wxXmlSubclassFactories *wxXmlResource::ms_subclassFactories = NULL;
2b5f62a0
VZ
844
845/*static*/ void wxXmlResource::AddSubclassFactory(wxXmlSubclassFactory *factory)
846{
847 if (!ms_subclassFactories)
848 {
eb2d0d23 849 ms_subclassFactories = new wxXmlSubclassFactories;
2b5f62a0 850 }
eb2d0d23 851 ms_subclassFactories->push_back(factory);
2b5f62a0
VZ
852}
853
854class wxXmlSubclassFactoryCXX : public wxXmlSubclassFactory
855{
856public:
857 ~wxXmlSubclassFactoryCXX() {}
858
859 wxObject *Create(const wxString& className)
860 {
861 wxClassInfo* classInfo = wxClassInfo::FindClass(className);
862
863 if (classInfo)
864 return classInfo->CreateObject();
865 else
866 return NULL;
867 }
868};
869
870
871
78d14f80 872
78d14f80
VS
873wxXmlResourceHandler::wxXmlResourceHandler()
874 : m_node(NULL), m_parent(NULL), m_instance(NULL),
9a8d8c5a 875 m_parentAsWindow(NULL)
78d14f80
VS
876{}
877
878
879
880wxObject *wxXmlResourceHandler::CreateResource(wxXmlNode *node, wxObject *parent, wxObject *instance)
881{
882 wxXmlNode *myNode = m_node;
883 wxString myClass = m_class;
884 wxObject *myParent = m_parent, *myInstance = m_instance;
9a8d8c5a 885 wxWindow *myParentAW = m_parentAsWindow;
78d14f80 886
daa85ee3 887 m_instance = instance;
288b6107 888 if (!m_instance && node->HasAttribute(wxT("subclass")) &&
daa85ee3
VS
889 !(m_resource->GetFlags() & wxXRC_NO_SUBCLASSING))
890 {
288b6107 891 wxString subclass = node->GetAttribute(wxT("subclass"), wxEmptyString);
2b5f62a0 892 if (!subclass.empty())
daa85ee3 893 {
eb2d0d23
VS
894 for (wxXmlSubclassFactories::iterator i = wxXmlResource::ms_subclassFactories->begin();
895 i != wxXmlResource::ms_subclassFactories->end(); ++i)
2b5f62a0 896 {
eb2d0d23 897 m_instance = (*i)->Create(subclass);
2b5f62a0
VZ
898 if (m_instance)
899 break;
900 }
daa85ee3 901
2b5f62a0
VZ
902 if (!m_instance)
903 {
288b6107 904 wxString name = node->GetAttribute(wxT("name"), wxEmptyString);
819559b2
VS
905 ReportError
906 (
907 node,
908 wxString::Format
909 (
910 "subclass \"%s\" not found for resource \"%s\", not subclassing",
911 subclass, name
912 )
913 );
2b5f62a0
VZ
914 }
915 }
daa85ee3
VS
916 }
917
78d14f80 918 m_node = node;
288b6107 919 m_class = node->GetAttribute(wxT("class"), wxEmptyString);
78d14f80 920 m_parent = parent;
78d14f80 921 m_parentAsWindow = wxDynamicCast(m_parent, wxWindow);
78d14f80
VS
922
923 wxObject *returned = DoCreateResource();
924
925 m_node = myNode;
926 m_class = myClass;
927 m_parent = myParent; m_parentAsWindow = myParentAW;
9a8d8c5a 928 m_instance = myInstance;
78d14f80
VS
929
930 return returned;
931}
932
933
934void wxXmlResourceHandler::AddStyle(const wxString& name, int value)
935{
936 m_styleNames.Add(name);
937 m_styleValues.Add(value);
938}
939
940
941
942void wxXmlResourceHandler::AddWindowStyles()
943{
9dc579b3 944 XRC_ADD_STYLE(wxCLIP_CHILDREN);
d54a3e73
VZ
945
946 // the border styles all have the old and new names, recognize both for now
947 XRC_ADD_STYLE(wxSIMPLE_BORDER); XRC_ADD_STYLE(wxBORDER_SIMPLE);
948 XRC_ADD_STYLE(wxSUNKEN_BORDER); XRC_ADD_STYLE(wxBORDER_SUNKEN);
949 XRC_ADD_STYLE(wxDOUBLE_BORDER); XRC_ADD_STYLE(wxBORDER_DOUBLE);
950 XRC_ADD_STYLE(wxRAISED_BORDER); XRC_ADD_STYLE(wxBORDER_RAISED);
951 XRC_ADD_STYLE(wxSTATIC_BORDER); XRC_ADD_STYLE(wxBORDER_STATIC);
952 XRC_ADD_STYLE(wxNO_BORDER); XRC_ADD_STYLE(wxBORDER_NONE);
953
daa85ee3
VS
954 XRC_ADD_STYLE(wxTRANSPARENT_WINDOW);
955 XRC_ADD_STYLE(wxWANTS_CHARS);
43840d8b 956 XRC_ADD_STYLE(wxTAB_TRAVERSAL);
daa85ee3 957 XRC_ADD_STYLE(wxNO_FULL_REPAINT_ON_RESIZE);
7539ba56 958 XRC_ADD_STYLE(wxFULL_REPAINT_ON_RESIZE);
162a4f93 959 XRC_ADD_STYLE(wxALWAYS_SHOW_SB);
9f4ed861 960 XRC_ADD_STYLE(wxWS_EX_BLOCK_EVENTS);
b0802e64 961 XRC_ADD_STYLE(wxWS_EX_VALIDATE_RECURSIVELY);
78d14f80
VS
962}
963
964
965
966bool wxXmlResourceHandler::HasParam(const wxString& param)
967{
968 return (GetParamNode(param) != NULL);
969}
970
971
972int wxXmlResourceHandler::GetStyle(const wxString& param, int defaults)
973{
974 wxString s = GetParamValue(param);
975
976 if (!s) return defaults;
977
2b5f62a0 978 wxStringTokenizer tkn(s, wxT("| \t\n"), wxTOKEN_STRTOK);
78d14f80
VS
979 int style = 0;
980 int index;
981 wxString fl;
982 while (tkn.HasMoreTokens())
983 {
984 fl = tkn.GetNextToken();
985 index = m_styleNames.Index(fl);
986 if (index != wxNOT_FOUND)
819559b2 987 {
78d14f80 988 style |= m_styleValues[index];
819559b2 989 }
78d14f80 990 else
819559b2
VS
991 {
992 ReportParamError
993 (
994 param,
995 wxString::Format("unknown style flag \"%s\"", fl)
996 );
997 }
78d14f80
VS
998 }
999 return style;
1000}
1001
1002
1003
ee1046d1 1004wxString wxXmlResourceHandler::GetText(const wxString& param, bool translate)
78d14f80 1005{
7b56015f
VS
1006 wxXmlNode *parNode = GetParamNode(param);
1007 wxString str1(GetNodeContent(parNode));
78d14f80 1008 wxString str2;
424af7aa
VS
1009
1010 // "\\" wasn't translated to "\" prior to 2.5.3.0:
1011 const bool escapeBackslash = (m_resource->CompareVersion(2,5,3,0) >= 0);
78d14f80 1012
b272b6dc
RD
1013 // VS: First version of XRC resources used $ instead of & (which is
1014 // illegal in XML), but later I realized that '_' fits this purpose
718cf160 1015 // much better (because &File means "File with F underlined").
424af7aa
VS
1016 const wxChar amp_char = (m_resource->CompareVersion(2,3,0,1) < 0)
1017 ? '$' : '_';
78d14f80 1018
424af7aa 1019 for ( wxString::const_iterator dt = str1.begin(); dt != str1.end(); ++dt )
78d14f80
VS
1020 {
1021 // Remap amp_char to &, map double amp_char to amp_char (for things
1022 // like "&File..." -- this is illegal in XML, so we use "_File..."):
424af7aa 1023 if ( *dt == amp_char )
78d14f80
VS
1024 {
1025 if ( *(++dt) == amp_char )
1026 str2 << amp_char;
1027 else
1028 str2 << wxT('&') << *dt;
1029 }
984c33c9 1030 // Remap \n to CR, \r to LF, \t to TAB, \\ to \:
424af7aa
VS
1031 else if ( *dt == wxT('\\') )
1032 {
1033 switch ( (*(++dt)).GetValue() )
78d14f80 1034 {
984c33c9
VS
1035 case wxT('n'):
1036 str2 << wxT('\n');
1037 break;
e7a3a5a5 1038
984c33c9
VS
1039 case wxT('t'):
1040 str2 << wxT('\t');
1041 break;
e7a3a5a5 1042
984c33c9
VS
1043 case wxT('r'):
1044 str2 << wxT('\r');
1045 break;
1046
1047 case wxT('\\') :
1048 // "\\" wasn't translated to "\" prior to 2.5.3.0:
424af7aa 1049 if ( escapeBackslash )
984c33c9
VS
1050 {
1051 str2 << wxT('\\');
1052 break;
1053 }
1054 // else fall-through to default: branch below
e7a3a5a5 1055
984c33c9
VS
1056 default:
1057 str2 << wxT('\\') << *dt;
1058 break;
78d14f80 1059 }
424af7aa
VS
1060 }
1061 else
1062 {
1063 str2 << *dt;
1064 }
78d14f80 1065 }
b272b6dc 1066
7b56015f
VS
1067 if (m_resource->GetFlags() & wxXRC_USE_LOCALE)
1068 {
1069 if (translate && parNode &&
288b6107 1070 parNode->GetAttribute(wxT("translate"), wxEmptyString) != wxT("0"))
7b56015f 1071 {
d4a724d4 1072 return wxGetTranslation(str2, m_resource->GetDomain());
7b56015f
VS
1073 }
1074 else
1075 {
1076#if wxUSE_UNICODE
1077 return str2;
1078#else
1079 // The string is internally stored as UTF-8, we have to convert
1080 // it into system's default encoding so that it can be displayed:
6251e0ea 1081 return wxString(str2.wc_str(wxConvUTF8), wxConvLocal);
7b56015f
VS
1082#endif
1083 }
1084 }
8516a98b
DS
1085
1086 // If wxXRC_USE_LOCALE is not set, then the string is already in
1087 // system's default encoding in ANSI build, so we don't have to
1088 // do anything special here.
1089 return str2;
78d14f80
VS
1090}
1091
1092
1093
1094long wxXmlResourceHandler::GetLong(const wxString& param, long defaultv)
1095{
1096 long value;
1097 wxString str1 = GetParamValue(param);
1098
1099 if (!str1.ToLong(&value))
1100 value = defaultv;
1101
1102 return value;
1103}
e7a3a5a5 1104
1df61962
VS
1105float wxXmlResourceHandler::GetFloat(const wxString& param, float defaultv)
1106{
1d9473d3 1107 wxString str = GetParamValue(param);
1df61962 1108
cfd91598 1109#if wxUSE_INTL
1d9473d3
VZ
1110 // strings in XRC always use C locale but wxString::ToDouble() uses the
1111 // current one, so transform the string to it supposing that the only
1112 // difference between them is the decimal separator
1113 //
1114 // TODO: use wxString::ToCDouble() when we have it
1115 str.Replace(wxT("."), wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT,
1116 wxLOCALE_CAT_NUMBER));
cfd91598 1117#endif // wxUSE_INTL
e7a3a5a5 1118
1d9473d3
VZ
1119 double value;
1120 if (!str.ToDouble(&value))
1df61962
VS
1121 value = defaultv;
1122
17a1ebd1 1123 return wx_truncate_cast(float, value);
1df61962 1124}
78d14f80 1125
af1337b0 1126
78d14f80
VS
1127int wxXmlResourceHandler::GetID()
1128{
13de23f6 1129 return wxXmlResource::GetXRCID(GetName());
78d14f80
VS
1130}
1131
1132
af1337b0 1133
78d14f80
VS
1134wxString wxXmlResourceHandler::GetName()
1135{
288b6107 1136 return m_node->GetAttribute(wxT("name"), wxT("-1"));
78d14f80
VS
1137}
1138
1139
1140
8758875e
VZ
1141bool wxXmlResourceHandler::GetBoolAttr(const wxString& attr, bool defaultv)
1142{
1143 wxString v;
1144 return m_node->GetAttribute(attr, &v) ? v == '1' : defaultv;
1145}
1146
78d14f80
VS
1147bool wxXmlResourceHandler::GetBool(const wxString& param, bool defaultv)
1148{
8758875e 1149 const wxString v = GetParamValue(param);
8516a98b 1150
8758875e 1151 return v.empty() ? defaultv : (v == '1');
78d14f80
VS
1152}
1153
1154
1df61962
VS
1155static wxColour GetSystemColour(const wxString& name)
1156{
1157 if (!name.empty())
1158 {
1159 #define SYSCLR(clr) \
1160 if (name == _T(#clr)) return wxSystemSettings::GetColour(clr);
1161 SYSCLR(wxSYS_COLOUR_SCROLLBAR)
1162 SYSCLR(wxSYS_COLOUR_BACKGROUND)
1163 SYSCLR(wxSYS_COLOUR_DESKTOP)
1164 SYSCLR(wxSYS_COLOUR_ACTIVECAPTION)
1165 SYSCLR(wxSYS_COLOUR_INACTIVECAPTION)
1166 SYSCLR(wxSYS_COLOUR_MENU)
1167 SYSCLR(wxSYS_COLOUR_WINDOW)
1168 SYSCLR(wxSYS_COLOUR_WINDOWFRAME)
1169 SYSCLR(wxSYS_COLOUR_MENUTEXT)
1170 SYSCLR(wxSYS_COLOUR_WINDOWTEXT)
1171 SYSCLR(wxSYS_COLOUR_CAPTIONTEXT)
1172 SYSCLR(wxSYS_COLOUR_ACTIVEBORDER)
1173 SYSCLR(wxSYS_COLOUR_INACTIVEBORDER)
1174 SYSCLR(wxSYS_COLOUR_APPWORKSPACE)
1175 SYSCLR(wxSYS_COLOUR_HIGHLIGHT)
1176 SYSCLR(wxSYS_COLOUR_HIGHLIGHTTEXT)
1177 SYSCLR(wxSYS_COLOUR_BTNFACE)
1178 SYSCLR(wxSYS_COLOUR_3DFACE)
1179 SYSCLR(wxSYS_COLOUR_BTNSHADOW)
1180 SYSCLR(wxSYS_COLOUR_3DSHADOW)
1181 SYSCLR(wxSYS_COLOUR_GRAYTEXT)
1182 SYSCLR(wxSYS_COLOUR_BTNTEXT)
1183 SYSCLR(wxSYS_COLOUR_INACTIVECAPTIONTEXT)
1184 SYSCLR(wxSYS_COLOUR_BTNHIGHLIGHT)
1185 SYSCLR(wxSYS_COLOUR_BTNHILIGHT)
1186 SYSCLR(wxSYS_COLOUR_3DHIGHLIGHT)
1187 SYSCLR(wxSYS_COLOUR_3DHILIGHT)
1188 SYSCLR(wxSYS_COLOUR_3DDKSHADOW)
1189 SYSCLR(wxSYS_COLOUR_3DLIGHT)
1190 SYSCLR(wxSYS_COLOUR_INFOTEXT)
1191 SYSCLR(wxSYS_COLOUR_INFOBK)
1192 SYSCLR(wxSYS_COLOUR_LISTBOX)
1193 SYSCLR(wxSYS_COLOUR_HOTLIGHT)
1194 SYSCLR(wxSYS_COLOUR_GRADIENTACTIVECAPTION)
1195 SYSCLR(wxSYS_COLOUR_GRADIENTINACTIVECAPTION)
1196 SYSCLR(wxSYS_COLOUR_MENUHILIGHT)
1197 SYSCLR(wxSYS_COLOUR_MENUBAR)
1198 #undef SYSCLR
1199 }
1200
1201 return wxNullColour;
1202}
78d14f80 1203
984f1d84 1204wxColour wxXmlResourceHandler::GetColour(const wxString& param, const wxColour& defaultv)
78d14f80
VS
1205{
1206 wxString v = GetParamValue(param);
984f1d84
VS
1207
1208 if ( v.empty() )
1209 return defaultv;
1210
68b4e4cf 1211 wxColour clr;
1df61962 1212
68b4e4cf
WS
1213 // wxString -> wxColour conversion
1214 if (!clr.Set(v))
78d14f80 1215 {
1df61962
VS
1216 // the colour doesn't use #RRGGBB format, check if it is symbolic
1217 // colour name:
68b4e4cf 1218 clr = GetSystemColour(v);
1df61962
VS
1219 if (clr.Ok())
1220 return clr;
e7a3a5a5 1221
819559b2
VS
1222 ReportParamError
1223 (
1224 param,
1225 wxString::Format("incorrect colour specification \"%s\"", v)
1226 );
78d14f80
VS
1227 return wxNullColour;
1228 }
1229
68b4e4cf 1230 return clr;
78d14f80
VS
1231}
1232
1233
1234
92e898b0 1235wxBitmap wxXmlResourceHandler::GetBitmap(const wxString& param,
db59a97c
VS
1236 const wxArtClient& defaultArtClient,
1237 wxSize size)
78d14f80 1238{
db59a97c
VS
1239 /* If the bitmap is specified as stock item, query wxArtProvider for it: */
1240 wxXmlNode *bmpNode = GetParamNode(param);
1241 if ( bmpNode )
af1337b0 1242 {
288b6107 1243 wxString sid = bmpNode->GetAttribute(wxT("stock_id"), wxEmptyString);
db59a97c
VS
1244 if ( !sid.empty() )
1245 {
288b6107 1246 wxString scl = bmpNode->GetAttribute(wxT("stock_client"), wxEmptyString);
b3e85292
VS
1247 if (scl.empty())
1248 scl = defaultArtClient;
1249 else
1250 scl = wxART_MAKE_CLIENT_ID_FROM_STR(scl);
e7a3a5a5 1251
92e898b0 1252 wxBitmap stockArt =
db59a97c 1253 wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(sid),
b3e85292 1254 scl, size);
db59a97c
VS
1255 if ( stockArt.Ok() )
1256 return stockArt;
1257 }
af1337b0
JS
1258 }
1259
92e898b0 1260 /* ...or load the bitmap from file: */
78d14f80 1261 wxString name = GetParamValue(param);
e7a3a5a5 1262 if (name.empty()) return wxNullBitmap;
78d14f80 1263#if wxUSE_FILESYSTEM
4532786e 1264 wxFSFile *fsfile = GetCurFileSystem().OpenFile(name, wxFS_READ | wxFS_SEEKABLE);
78d14f80
VS
1265 if (fsfile == NULL)
1266 {
819559b2
VS
1267 ReportParamError
1268 (
1269 param,
1270 wxString::Format("cannot open bitmap resource \"%s\"", name)
1271 );
78d14f80
VS
1272 return wxNullBitmap;
1273 }
1274 wxImage img(*(fsfile->GetStream()));
1275 delete fsfile;
1276#else
45f3249b 1277 wxImage img(name);
78d14f80 1278#endif
af1337b0 1279
78d14f80
VS
1280 if (!img.Ok())
1281 {
819559b2
VS
1282 ReportParamError
1283 (
1284 param,
1285 wxString::Format("cannot create bitmap from \"%s\"", name)
1286 );
78d14f80
VS
1287 return wxNullBitmap;
1288 }
1289 if (!(size == wxDefaultSize)) img.Rescale(size.x, size.y);
b272b6dc 1290 return wxBitmap(img);
78d14f80
VS
1291}
1292
78d14f80 1293
92e898b0 1294wxIcon wxXmlResourceHandler::GetIcon(const wxString& param,
db59a97c
VS
1295 const wxArtClient& defaultArtClient,
1296 wxSize size)
78d14f80 1297{
78d14f80 1298 wxIcon icon;
db59a97c 1299 icon.CopyFromBitmap(GetBitmap(param, defaultArtClient, size));
78d14f80
VS
1300 return icon;
1301}
1302
1303
1304
1305wxXmlNode *wxXmlResourceHandler::GetParamNode(const wxString& param)
1306{
2b5f62a0
VZ
1307 wxCHECK_MSG(m_node, NULL, wxT("You can't access handler data before it was initialized!"));
1308
78d14f80
VS
1309 wxXmlNode *n = m_node->GetChildren();
1310
1311 while (n)
1312 {
1313 if (n->GetType() == wxXML_ELEMENT_NODE && n->GetName() == param)
cffff062
VZ
1314 {
1315 // TODO: check that there are no other properties/parameters with
1316 // the same name and log an error if there are (can't do this
1317 // right now as I'm not sure if it's not going to break code
1318 // using this function in unintentional way (i.e. for
1319 // accessing other things than properties), for example
1320 // wxBitmapComboBoxXmlHandler almost surely does
78d14f80 1321 return n;
cffff062 1322 }
78d14f80
VS
1323 n = n->GetNext();
1324 }
1325 return NULL;
1326}
1327
2d672c46
MW
1328bool wxXmlResourceHandler::IsOfClass(wxXmlNode *node, const wxString& classname)
1329{
288b6107 1330 return node->GetAttribute(wxT("class"), wxEmptyString) == classname;
2d672c46
MW
1331}
1332
1333
1334
78d14f80
VS
1335wxString wxXmlResourceHandler::GetNodeContent(wxXmlNode *node)
1336{
1337 wxXmlNode *n = node;
1338 if (n == NULL) return wxEmptyString;
1339 n = n->GetChildren();
1340
1341 while (n)
1342 {
1343 if (n->GetType() == wxXML_TEXT_NODE ||
1344 n->GetType() == wxXML_CDATA_SECTION_NODE)
1345 return n->GetContent();
1346 n = n->GetNext();
1347 }
1348 return wxEmptyString;
1349}
1350
1351
1352
1353wxString wxXmlResourceHandler::GetParamValue(const wxString& param)
1354{
e7a3a5a5 1355 if (param.empty())
78d14f80
VS
1356 return GetNodeContent(m_node);
1357 else
1358 return GetNodeContent(GetParamNode(param));
1359}
1360
1361
1362
0c00c86f
VS
1363wxSize wxXmlResourceHandler::GetSize(const wxString& param,
1364 wxWindow *windowToUse)
78d14f80
VS
1365{
1366 wxString s = GetParamValue(param);
e7a3a5a5 1367 if (s.empty()) s = wxT("-1,-1");
78d14f80 1368 bool is_dlg;
d1f47235 1369 long sx, sy = 0;
78d14f80 1370
88a7a4e1 1371 is_dlg = s[s.length()-1] == wxT('d');
78d14f80
VS
1372 if (is_dlg) s.RemoveLast();
1373
1374 if (!s.BeforeFirst(wxT(',')).ToLong(&sx) ||
1375 !s.AfterLast(wxT(',')).ToLong(&sy))
1376 {
819559b2
VS
1377 ReportParamError
1378 (
1379 param,
1380 wxString::Format("cannot parse coordinates value \"%s\"", s)
1381 );
78d14f80
VS
1382 return wxDefaultSize;
1383 }
1384
1385 if (is_dlg)
1386 {
0c00c86f
VS
1387 if (windowToUse)
1388 {
1389 return wxDLG_UNIT(windowToUse, wxSize(sx, sy));
1390 }
1391 else if (m_parentAsWindow)
1392 {
78d14f80 1393 return wxDLG_UNIT(m_parentAsWindow, wxSize(sx, sy));
0c00c86f 1394 }
78d14f80
VS
1395 else
1396 {
819559b2
VS
1397 ReportParamError
1398 (
1399 param,
1400 "cannot convert dialog units: dialog unknown"
1401 );
78d14f80
VS
1402 return wxDefaultSize;
1403 }
1404 }
8516a98b
DS
1405
1406 return wxSize(sx, sy);
78d14f80
VS
1407}
1408
1409
1410
1411wxPoint wxXmlResourceHandler::GetPosition(const wxString& param)
1412{
1413 wxSize sz = GetSize(param);
1414 return wxPoint(sz.x, sz.y);
1415}
1416
1417
1418
0c00c86f
VS
1419wxCoord wxXmlResourceHandler::GetDimension(const wxString& param,
1420 wxCoord defaultv,
1421 wxWindow *windowToUse)
78d14f80
VS
1422{
1423 wxString s = GetParamValue(param);
e7a3a5a5 1424 if (s.empty()) return defaultv;
78d14f80
VS
1425 bool is_dlg;
1426 long sx;
1427
88a7a4e1 1428 is_dlg = s[s.length()-1] == wxT('d');
78d14f80
VS
1429 if (is_dlg) s.RemoveLast();
1430
1431 if (!s.ToLong(&sx))
1432 {
819559b2
VS
1433 ReportParamError
1434 (
1435 param,
1436 wxString::Format("cannot parse dimension value \"%s\"", s)
1437 );
78d14f80
VS
1438 return defaultv;
1439 }
1440
1441 if (is_dlg)
1442 {
0c00c86f
VS
1443 if (windowToUse)
1444 {
1445 return wxDLG_UNIT(windowToUse, wxSize(sx, 0)).x;
1446 }
1447 else if (m_parentAsWindow)
1448 {
78d14f80 1449 return wxDLG_UNIT(m_parentAsWindow, wxSize(sx, 0)).x;
0c00c86f 1450 }
78d14f80
VS
1451 else
1452 {
819559b2
VS
1453 ReportParamError
1454 (
1455 param,
1456 "cannot convert dialog units: dialog unknown"
1457 );
78d14f80
VS
1458 return defaultv;
1459 }
1460 }
8516a98b
DS
1461
1462 return sx;
78d14f80
VS
1463}
1464
1465
1df61962
VS
1466// Get system font index using indexname
1467static wxFont GetSystemFont(const wxString& name)
1468{
1469 if (!name.empty())
1470 {
1471 #define SYSFNT(fnt) \
1472 if (name == _T(#fnt)) return wxSystemSettings::GetFont(fnt);
1473 SYSFNT(wxSYS_OEM_FIXED_FONT)
1474 SYSFNT(wxSYS_ANSI_FIXED_FONT)
1475 SYSFNT(wxSYS_ANSI_VAR_FONT)
1476 SYSFNT(wxSYS_SYSTEM_FONT)
1477 SYSFNT(wxSYS_DEVICE_DEFAULT_FONT)
1df61962
VS
1478 SYSFNT(wxSYS_SYSTEM_FIXED_FONT)
1479 SYSFNT(wxSYS_DEFAULT_GUI_FONT)
1480 #undef SYSFNT
1481 }
1482
1483 return wxNullFont;
1484}
78d14f80
VS
1485
1486wxFont wxXmlResourceHandler::GetFont(const wxString& param)
1487{
1488 wxXmlNode *font_node = GetParamNode(param);
1489 if (font_node == NULL)
1490 {
819559b2
VS
1491 ReportError(
1492 wxString::Format("cannot find font node \"%s\"", param));
78d14f80
VS
1493 return wxNullFont;
1494 }
1495
1496 wxXmlNode *oldnode = m_node;
1497 m_node = font_node;
1498
1df61962 1499 // font attributes:
78d14f80 1500
1df61962 1501 // size
94245f6d 1502 int isize = -1;
1df61962 1503 bool hasSize = HasParam(wxT("size"));
e7a3a5a5 1504 if (hasSize)
94245f6d 1505 isize = GetLong(wxT("size"), -1);
78d14f80 1506
1df61962
VS
1507 // style
1508 int istyle = wxNORMAL;
1509 bool hasStyle = HasParam(wxT("style"));
1510 if (hasStyle)
1511 {
1512 wxString style = GetParamValue(wxT("style"));
e7a3a5a5 1513 if (style == wxT("italic"))
1df61962 1514 istyle = wxITALIC;
e7a3a5a5 1515 else if (style == wxT("slant"))
1df61962
VS
1516 istyle = wxSLANT;
1517 }
78d14f80 1518
1df61962
VS
1519 // weight
1520 int iweight = wxNORMAL;
1521 bool hasWeight = HasParam(wxT("weight"));
1522 if (hasWeight)
1523 {
1524 wxString weight = GetParamValue(wxT("weight"));
e7a3a5a5 1525 if (weight == wxT("bold"))
1df61962 1526 iweight = wxBOLD;
e7a3a5a5 1527 else if (weight == wxT("light"))
1df61962
VS
1528 iweight = wxLIGHT;
1529 }
e7a3a5a5 1530
1df61962
VS
1531 // underline
1532 bool hasUnderlined = HasParam(wxT("underlined"));
1533 bool underlined = hasUnderlined ? GetBool(wxT("underlined"), false) : false;
78d14f80 1534
1df61962
VS
1535 // family and facename
1536 int ifamily = wxDEFAULT;
1537 bool hasFamily = HasParam(wxT("family"));
1538 if (hasFamily)
78d14f80 1539 {
1df61962
VS
1540 wxString family = GetParamValue(wxT("family"));
1541 if (family == wxT("decorative")) ifamily = wxDECORATIVE;
1542 else if (family == wxT("roman")) ifamily = wxROMAN;
1543 else if (family == wxT("script")) ifamily = wxSCRIPT;
1544 else if (family == wxT("swiss")) ifamily = wxSWISS;
1545 else if (family == wxT("modern")) ifamily = wxMODERN;
1546 else if (family == wxT("teletype")) ifamily = wxTELETYPE;
1547 }
e7a3a5a5
WS
1548
1549
1df61962
VS
1550 wxString facename;
1551 bool hasFacename = HasParam(wxT("face"));
1552 if (hasFacename)
1553 {
1554 wxString faces = GetParamValue(wxT("face"));
1df61962 1555 wxStringTokenizer tk(faces, wxT(","));
63feebce
VS
1556#if wxUSE_FONTENUM
1557 wxArrayString facenames(wxFontEnumerator::GetFacenames());
1df61962 1558 while (tk.HasMoreTokens())
78d14f80 1559 {
6540132f 1560 int index = facenames.Index(tk.GetNextToken(), false);
1df61962
VS
1561 if (index != wxNOT_FOUND)
1562 {
6540132f 1563 facename = facenames[index];
1df61962
VS
1564 break;
1565 }
78d14f80 1566 }
63feebce
VS
1567#else // !wxUSE_FONTENUM
1568 // just use the first face name if we can't check its availability:
1569 if (tk.HasMoreTokens())
1570 facename = tk.GetNextToken();
1571#endif // wxUSE_FONTENUM/!wxUSE_FONTENUM
78d14f80
VS
1572 }
1573
1df61962
VS
1574 // encoding
1575 wxFontEncoding enc = wxFONTENCODING_DEFAULT;
1576 bool hasEncoding = HasParam(wxT("encoding"));
1577 if (hasEncoding)
1578 {
1579 wxString encoding = GetParamValue(wxT("encoding"));
1580 wxFontMapper mapper;
e7a3a5a5 1581 if (!encoding.empty())
1df61962
VS
1582 enc = mapper.CharsetToEncoding(encoding);
1583 if (enc == wxFONTENCODING_SYSTEM)
1584 enc = wxFONTENCODING_DEFAULT;
1585 }
78d14f80 1586
1df61962 1587 // is this font based on a system font?
94245f6d 1588 wxFont font = GetSystemFont(GetParamValue(wxT("sysfont")));
e7a3a5a5 1589
94245f6d 1590 if (font.Ok())
1df61962 1591 {
94245f6d
VZ
1592 if (hasSize && isize != -1)
1593 font.SetPointSize(isize);
1df61962 1594 else if (HasParam(wxT("relativesize")))
94245f6d 1595 font.SetPointSize(int(font.GetPointSize() *
1df61962 1596 GetFloat(wxT("relativesize"))));
e7a3a5a5 1597
1df61962 1598 if (hasStyle)
94245f6d 1599 font.SetStyle(istyle);
1df61962 1600 if (hasWeight)
94245f6d 1601 font.SetWeight(iweight);
1df61962 1602 if (hasUnderlined)
94245f6d 1603 font.SetUnderlined(underlined);
1df61962 1604 if (hasFamily)
94245f6d 1605 font.SetFamily(ifamily);
1df61962 1606 if (hasFacename)
94245f6d 1607 font.SetFaceName(facename);
1df61962 1608 if (hasEncoding)
94245f6d
VZ
1609 font.SetDefaultEncoding(enc);
1610 }
1611 else // not based on system font
1612 {
1613 font = wxFont(isize == -1 ? wxNORMAL_FONT->GetPointSize() : isize,
1614 ifamily, istyle, iweight,
1615 underlined, facename, enc);
1df61962 1616 }
8516a98b
DS
1617
1618 m_node = oldnode;
94245f6d 1619 return font;
78d14f80
VS
1620}
1621
1622
1623void wxXmlResourceHandler::SetupWindow(wxWindow *wnd)
1624{
1625 //FIXME : add cursor
1626
1627 if (HasParam(wxT("exstyle")))
0099f343
JS
1628 // Have to OR it with existing style, since
1629 // some implementations (e.g. wxGTK) use the extra style
1630 // during creation
1631 wnd->SetExtraStyle(wnd->GetExtraStyle() | GetStyle(wxT("exstyle")));
78d14f80
VS
1632 if (HasParam(wxT("bg")))
1633 wnd->SetBackgroundColour(GetColour(wxT("bg")));
1634 if (HasParam(wxT("fg")))
1635 wnd->SetForegroundColour(GetColour(wxT("fg")));
1636 if (GetBool(wxT("enabled"), 1) == 0)
f80ea77b 1637 wnd->Enable(false);
78d14f80
VS
1638 if (GetBool(wxT("focused"), 0) == 1)
1639 wnd->SetFocus();
1640 if (GetBool(wxT("hidden"), 0) == 1)
f80ea77b 1641 wnd->Show(false);
78d14f80
VS
1642#if wxUSE_TOOLTIPS
1643 if (HasParam(wxT("tooltip")))
1644 wnd->SetToolTip(GetText(wxT("tooltip")));
1645#endif
1646 if (HasParam(wxT("font")))
1647 wnd->SetFont(GetFont());
b23030d6
JS
1648 if (HasParam(wxT("help")))
1649 wnd->SetHelpText(GetText(wxT("help")));
78d14f80
VS
1650}
1651
1652
1653void wxXmlResourceHandler::CreateChildren(wxObject *parent, bool this_hnd_only)
1654{
23239d94 1655 for ( wxXmlNode *n = m_node->GetChildren(); n; n = n->GetNext() )
78d14f80 1656 {
23239d94 1657 if ( IsObjectNode(n) )
78d14f80 1658 {
317a0d73
VS
1659 m_resource->CreateResFromNode(n, parent, NULL,
1660 this_hnd_only ? this : NULL);
78d14f80 1661 }
78d14f80
VS
1662 }
1663}
1664
1665
1666void wxXmlResourceHandler::CreateChildrenPrivately(wxObject *parent, wxXmlNode *rootnode)
1667{
1668 wxXmlNode *root;
1669 if (rootnode == NULL) root = m_node; else root = rootnode;
1670 wxXmlNode *n = root->GetChildren();
1671
1672 while (n)
1673 {
1674 if (n->GetType() == wxXML_ELEMENT_NODE && CanHandle(n))
1675 {
1676 CreateResource(n, parent, NULL);
1677 }
1678 n = n->GetNext();
1679 }
1680}
1681
1682
819559b2
VS
1683//-----------------------------------------------------------------------------
1684// errors reporting
1685//-----------------------------------------------------------------------------
1686
1687void wxXmlResourceHandler::ReportError(const wxString& message)
1688{
1689 m_resource->ReportError(m_node, message);
1690}
1691
1692void wxXmlResourceHandler::ReportError(wxXmlNode *context,
1693 const wxString& message)
1694{
1695 m_resource->ReportError(context ? context : m_node, message);
1696}
1697
1698void wxXmlResourceHandler::ReportParamError(const wxString& param,
1699 const wxString& message)
1700{
1701 m_resource->ReportError(GetParamNode(param), message);
1702}
1703
1704namespace
1705{
1706
1707wxString
1708GetFileNameFromNode(wxXmlNode *node, const wxXmlResourceDataRecords& files)
1709{
1710 wxXmlNode *root = node;
1711 while ( root->GetParent() )
1712 root = root->GetParent();
1713
1714 for ( wxXmlResourceDataRecords::const_iterator i = files.begin();
1715 i != files.end(); ++i )
1716 {
1717 if ( (*i)->Doc->GetRoot() == root )
1718 {
1719 return (*i)->File;
1720 }
1721 }
1722
1723 return wxEmptyString; // not found
1724}
1725
1726} // anonymous namespace
1727
1728void wxXmlResource::ReportError(wxXmlNode *context, const wxString& message)
1729{
1730 if ( !context )
1731 {
1732 DoReportError("", NULL, message);
1733 return;
1734 }
78d14f80 1735
819559b2
VS
1736 // We need to find out the file that 'context' is part of. Performance of
1737 // this code is not critical, so we simply find the root XML node and
1738 // compare it with all loaded XRC files.
1739 const wxString filename = GetFileNameFromNode(context, Data());
78d14f80 1740
819559b2
VS
1741 DoReportError(filename, context, message);
1742}
78d14f80 1743
819559b2
VS
1744void wxXmlResource::DoReportError(const wxString& xrcFile, wxXmlNode *position,
1745 const wxString& message)
1746{
1747 const int line = position ? position->GetLineNumber() : -1;
1748
1749 wxString loc;
1750 if ( !xrcFile.empty() )
1751 loc = xrcFile + ':';
1752 if ( line != -1 )
1753 loc += wxString::Format("%d:", line);
1754 if ( !loc.empty() )
1755 loc += ' ';
1756
1757 wxLogError("XRC error: %s%s", loc, message);
1758}
78d14f80
VS
1759
1760
819559b2
VS
1761//-----------------------------------------------------------------------------
1762// XRCID implementation
1763//-----------------------------------------------------------------------------
78d14f80 1764
5ed345b7 1765#define XRCID_TABLE_SIZE 1024
78d14f80
VS
1766
1767
5ed345b7 1768struct XRCID_record
78d14f80 1769{
cf2810aa
VZ
1770 /* Hold the id so that once an id is allocated for a name, it
1771 does not get created again by NewControlId at least
1772 until we are done with it */
1773 wxWindowIDRef id;
c560da98 1774 char *key;
5ed345b7 1775 XRCID_record *next;
78d14f80
VS
1776};
1777
5ed345b7 1778static XRCID_record *XRCID_Records[XRCID_TABLE_SIZE] = {NULL};
78d14f80 1779
c560da98 1780static int XRCID_Lookup(const char *str_id, int value_if_not_found = wxID_NONE)
78d14f80 1781{
78d14f80
VS
1782 int index = 0;
1783
c560da98 1784 for (const char *c = str_id; *c != '\0'; c++) index += (int)*c;
5ed345b7 1785 index %= XRCID_TABLE_SIZE;
78d14f80 1786
5ed345b7 1787 XRCID_record *oldrec = NULL;
5ed345b7 1788 for (XRCID_record *rec = XRCID_Records[index]; rec; rec = rec->next)
78d14f80 1789 {
00393283 1790 if (wxStrcmp(rec->key, str_id) == 0)
78d14f80
VS
1791 {
1792 return rec->id;
1793 }
78d14f80
VS
1794 oldrec = rec;
1795 }
1796
5ed345b7
VS
1797 XRCID_record **rec_var = (oldrec == NULL) ?
1798 &XRCID_Records[index] : &oldrec->next;
1799 *rec_var = new XRCID_record;
00393283 1800 (*rec_var)->key = wxStrdup(str_id);
78d14f80
VS
1801 (*rec_var)->next = NULL;
1802
c560da98 1803 char *end;
9b2a7469 1804 if (value_if_not_found != wxID_NONE)
13de23f6 1805 (*rec_var)->id = value_if_not_found;
85452d74
VS
1806 else
1807 {
13de23f6
VS
1808 int asint = wxStrtol(str_id, &end, 10);
1809 if (*str_id && *end == 0)
1810 {
1811 // if str_id was integer, keep it verbosely:
1812 (*rec_var)->id = asint;
1813 }
1814 else
1815 {
f35fdf7e 1816 (*rec_var)->id = wxWindowBase::NewControlId();
13de23f6 1817 }
85452d74
VS
1818 }
1819
78d14f80
VS
1820 return (*rec_var)->id;
1821}
1822
3b2a000e
VS
1823static void AddStdXRCID_Records();
1824
9b2a7469 1825/*static*/
c560da98 1826int wxXmlResource::DoGetXRCID(const char *str_id, int value_if_not_found)
13de23f6 1827{
3b2a000e
VS
1828 static bool s_stdIDsAdded = false;
1829
1830 if ( !s_stdIDsAdded )
1831 {
1832 s_stdIDsAdded = true;
1833 AddStdXRCID_Records();
1834 }
1835
9b2a7469 1836 return XRCID_Lookup(str_id, value_if_not_found);
13de23f6
VS
1837}
1838
cc378c2d
VZ
1839/* static */
1840wxString wxXmlResource::FindXRCIDById(int numId)
1841{
1842 for ( int i = 0; i < XRCID_TABLE_SIZE; i++ )
1843 {
1844 for ( XRCID_record *rec = XRCID_Records[i]; rec; rec = rec->next )
1845 {
1846 if ( rec->id == numId )
1847 return wxString(rec->key);
1848 }
1849 }
1850
1851 return wxString();
1852}
78d14f80 1853
5ed345b7 1854static void CleanXRCID_Record(XRCID_record *rec)
78d14f80
VS
1855{
1856 if (rec)
1857 {
5ed345b7 1858 CleanXRCID_Record(rec->next);
f35fdf7e 1859
00393283 1860 free(rec->key);
78d14f80
VS
1861 delete rec;
1862 }
1863}
1864
5ed345b7 1865static void CleanXRCID_Records()
78d14f80 1866{
5ed345b7 1867 for (int i = 0; i < XRCID_TABLE_SIZE; i++)
139c5871 1868 {
5ed345b7 1869 CleanXRCID_Record(XRCID_Records[i]);
139c5871
VS
1870 XRCID_Records[i] = NULL;
1871 }
78d14f80
VS
1872}
1873
13de23f6
VS
1874static void AddStdXRCID_Records()
1875{
c560da98 1876#define stdID(id) XRCID_Lookup(#id, id)
13de23f6 1877 stdID(-1);
c369d4f1
VS
1878
1879 stdID(wxID_ANY);
1880 stdID(wxID_SEPARATOR);
e7a3a5a5 1881
c369d4f1
VS
1882 stdID(wxID_OPEN);
1883 stdID(wxID_CLOSE);
1884 stdID(wxID_NEW);
1885 stdID(wxID_SAVE);
1886 stdID(wxID_SAVEAS);
1887 stdID(wxID_REVERT);
1888 stdID(wxID_EXIT);
1889 stdID(wxID_UNDO);
1890 stdID(wxID_REDO);
1891 stdID(wxID_HELP);
1892 stdID(wxID_PRINT);
1893 stdID(wxID_PRINT_SETUP);
e63f19ba 1894 stdID(wxID_PAGE_SETUP);
c369d4f1
VS
1895 stdID(wxID_PREVIEW);
1896 stdID(wxID_ABOUT);
1897 stdID(wxID_HELP_CONTENTS);
1898 stdID(wxID_HELP_COMMANDS);
1899 stdID(wxID_HELP_PROCEDURES);
1900 stdID(wxID_HELP_CONTEXT);
13de23f6 1901 stdID(wxID_CLOSE_ALL);
c369d4f1 1902 stdID(wxID_PREFERENCES);
d73195fd 1903 stdID(wxID_EDIT);
c369d4f1
VS
1904 stdID(wxID_CUT);
1905 stdID(wxID_COPY);
1906 stdID(wxID_PASTE);
1907 stdID(wxID_CLEAR);
1908 stdID(wxID_FIND);
1909 stdID(wxID_DUPLICATE);
1910 stdID(wxID_SELECTALL);
1911 stdID(wxID_DELETE);
1912 stdID(wxID_REPLACE);
1913 stdID(wxID_REPLACE_ALL);
1914 stdID(wxID_PROPERTIES);
1915 stdID(wxID_VIEW_DETAILS);
1916 stdID(wxID_VIEW_LARGEICONS);
1917 stdID(wxID_VIEW_SMALLICONS);
1918 stdID(wxID_VIEW_LIST);
1919 stdID(wxID_VIEW_SORTDATE);
1920 stdID(wxID_VIEW_SORTNAME);
1921 stdID(wxID_VIEW_SORTSIZE);
1922 stdID(wxID_VIEW_SORTTYPE);
1923 stdID(wxID_FILE1);
1924 stdID(wxID_FILE2);
1925 stdID(wxID_FILE3);
1926 stdID(wxID_FILE4);
1927 stdID(wxID_FILE5);
1928 stdID(wxID_FILE6);
1929 stdID(wxID_FILE7);
1930 stdID(wxID_FILE8);
1931 stdID(wxID_FILE9);
1932 stdID(wxID_OK);
1933 stdID(wxID_CANCEL);
1934 stdID(wxID_APPLY);
1935 stdID(wxID_YES);
1936 stdID(wxID_NO);
1937 stdID(wxID_STATIC);
1938 stdID(wxID_FORWARD);
1939 stdID(wxID_BACKWARD);
1940 stdID(wxID_DEFAULT);
1941 stdID(wxID_MORE);
1942 stdID(wxID_SETUP);
1943 stdID(wxID_RESET);
1944 stdID(wxID_CONTEXT_HELP);
1945 stdID(wxID_YESTOALL);
1946 stdID(wxID_NOTOALL);
1947 stdID(wxID_ABORT);
1948 stdID(wxID_RETRY);
1949 stdID(wxID_IGNORE);
1950 stdID(wxID_ADD);
1951 stdID(wxID_REMOVE);
1952 stdID(wxID_UP);
1953 stdID(wxID_DOWN);
1954 stdID(wxID_HOME);
1955 stdID(wxID_REFRESH);
1956 stdID(wxID_STOP);
1957 stdID(wxID_INDEX);
1958 stdID(wxID_BOLD);
1959 stdID(wxID_ITALIC);
1960 stdID(wxID_JUSTIFY_CENTER);
1961 stdID(wxID_JUSTIFY_FILL);
1962 stdID(wxID_JUSTIFY_RIGHT);
1963 stdID(wxID_JUSTIFY_LEFT);
1964 stdID(wxID_UNDERLINE);
1965 stdID(wxID_INDENT);
1966 stdID(wxID_UNINDENT);
1967 stdID(wxID_ZOOM_100);
1968 stdID(wxID_ZOOM_FIT);
1969 stdID(wxID_ZOOM_IN);
1970 stdID(wxID_ZOOM_OUT);
1971 stdID(wxID_UNDELETE);
1972 stdID(wxID_REVERT_TO_SAVED);
1973 stdID(wxID_SYSTEM_MENU);
1974 stdID(wxID_CLOSE_FRAME);
1975 stdID(wxID_MOVE_FRAME);
1976 stdID(wxID_RESIZE_FRAME);
1977 stdID(wxID_MAXIMIZE_FRAME);
1978 stdID(wxID_ICONIZE_FRAME);
1979 stdID(wxID_RESTORE_FRAME);
6b1eedc1
VZ
1980 stdID(wxID_CDROM);
1981 stdID(wxID_CONVERT);
1982 stdID(wxID_EXECUTE);
1983 stdID(wxID_FLOPPY);
1984 stdID(wxID_HARDDISK);
1985 stdID(wxID_BOTTOM);
1986 stdID(wxID_FIRST);
1987 stdID(wxID_LAST);
1988 stdID(wxID_TOP);
1989 stdID(wxID_INFO);
1990 stdID(wxID_JUMP_TO);
1991 stdID(wxID_NETWORK);
1992 stdID(wxID_SELECT_COLOR);
1993 stdID(wxID_SELECT_FONT);
1994 stdID(wxID_SORT_ASCENDING);
1995 stdID(wxID_SORT_DESCENDING);
1996 stdID(wxID_SPELL_CHECK);
1997 stdID(wxID_STRIKETHROUGH);
c369d4f1 1998
13de23f6
VS
1999#undef stdID
2000}
78d14f80
VS
2001
2002
2003
2004
2005
819559b2
VS
2006//-----------------------------------------------------------------------------
2007// module and globals
2008//-----------------------------------------------------------------------------
78d14f80 2009
fd230129
VZ
2010// normally we would do the cleanup from wxXmlResourceModule::OnExit() but it
2011// can happen that some XRC records have been created because of the use of
2012// XRCID() in event tables, which happens during static objects initialization,
2013// but then the application initialization failed and so the wx modules were
2014// neither initialized nor cleaned up -- this static object does the cleanup in
2015// this case
2016static struct wxXRCStaticCleanup
2017{
2018 ~wxXRCStaticCleanup() { CleanXRCID_Records(); }
2019} s_staticCleanup;
2020
78d14f80
VS
2021class wxXmlResourceModule: public wxModule
2022{
2023DECLARE_DYNAMIC_CLASS(wxXmlResourceModule)
2024public:
2025 wxXmlResourceModule() {}
824e8eaa
VS
2026 bool OnInit()
2027 {
2b5f62a0 2028 wxXmlResource::AddSubclassFactory(new wxXmlSubclassFactoryCXX);
f80ea77b 2029 return true;
824e8eaa 2030 }
78d14f80
VS
2031 void OnExit()
2032 {
1542c42e 2033 delete wxXmlResource::Set(NULL);
461932ae 2034 if(wxXmlResource::ms_subclassFactories)
eb2d0d23
VS
2035 {
2036 for ( wxXmlSubclassFactories::iterator i = wxXmlResource::ms_subclassFactories->begin();
2037 i != wxXmlResource::ms_subclassFactories->end(); ++i )
2038 {
2039 delete *i;
2040 }
2041 wxDELETE(wxXmlResource::ms_subclassFactories);
2042 }
5ed345b7 2043 CleanXRCID_Records();
78d14f80
VS
2044 }
2045};
2046
2047IMPLEMENT_DYNAMIC_CLASS(wxXmlResourceModule, wxModule)
2048
2049
2050// When wxXml is loaded dynamically after the application is already running
2051// then the built-in module system won't pick this one up. Add it manually.
2052void wxXmlInitResourceModule()
2053{
2054 wxModule* module = new wxXmlResourceModule;
2055 module->Init();
2056 wxModule::RegisterModule(module);
2057}
a1e4ec87
VS
2058
2059#endif // wxUSE_XRC