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