From 1dce6f094ab0d67e576e1b172f8c60fe7f48287c Mon Sep 17 00:00:00 2001 From: =?utf8?q?V=C3=A1clav=20Slav=C3=ADk?= Date: Thu, 5 Feb 2004 21:58:29 +0000 Subject: [PATCH] applied patch 744616: WXRC extension for automated use (Eduardo Marques) git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@25520 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- contrib/utils/wxrc/wxrc.cpp | 173 +++++++++++++++++++++++++++++++++--- docs/changes.txt | 1 + docs/latex/wx/txrc.tex | 94 ++++++++++++++++++++ utils/wxrc/wxrc.cpp | 173 +++++++++++++++++++++++++++++++++--- 4 files changed, 415 insertions(+), 26 deletions(-) diff --git a/contrib/utils/wxrc/wxrc.cpp b/contrib/utils/wxrc/wxrc.cpp index 79362762e1..bc4a9df795 100644 --- a/contrib/utils/wxrc/wxrc.cpp +++ b/contrib/utils/wxrc/wxrc.cpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // Name: wxrc.cpp // Purpose: XML resource compiler -// Author: Vaclav Slavik +// Author: Vaclav Slavik, Eduardo Marques // Created: 2000/03/05 // RCS-ID: $Id$ // Copyright: (c) 2000 Vaclav Slavik @@ -33,16 +33,112 @@ #include "wx/wfstream.h" +class XRCWidgetData +{ +public: + XRCWidgetData(const wxString& vname,const wxString& vclass) + : m_class(vclass), m_name(vname) {} + const wxString& GetName() const { return m_name; } + const wxString& GetClass() const { return m_class; } +private: + wxString m_class; + wxString m_name; +}; +#include "wx/arrimpl.cpp" +WX_DECLARE_OBJARRAY(XRCWidgetData,ArrayOfXRCWidgetData); +WX_DEFINE_OBJARRAY(ArrayOfXRCWidgetData); + +class XRCWndClassData +{ +private: + wxString m_className; + wxString m_parentClassName; + ArrayOfXRCWidgetData m_wdata; + + void BrowseXmlNode(wxXmlNode* node) + { + wxString classValue; + wxString nameValue; + wxXmlNode* children; + while (node) + { + if (node->GetName() == _T("object") + && node->GetPropVal(_T("class"),&classValue) + && node->GetPropVal(_T("name"),&nameValue)) + { + m_wdata.Add(XRCWidgetData(nameValue,classValue)); + } + children = node->GetChildren(); + if (children) + BrowseXmlNode(children); + node = node->GetNext(); + } + } + +public: + XRCWndClassData(const wxString& className,const wxString& parentClassName, const wxXmlNode* node) : + m_className(className) , m_parentClassName(parentClassName) { + + BrowseXmlNode(node->GetChildren()); + + } + + const ArrayOfXRCWidgetData& GetWidgetData(){ + return m_wdata; + } + void GenerateHeaderCode(wxFFile& file){ + + file.Write(_T("class ") + m_className + _T(" : public ") + m_parentClassName + + _T(" {\nprotected:\n")); + for(size_t i=0;iLoadObject(this,NULL,\"") + + m_className + + +_T("\",\"") + + m_parentClassName + + _T("\");\n")); + for(size_t i=0;iGetChildren(); + wxString classValue,nameValue; + while(node){ + if(node->GetName() == _T("object") + && node->GetPropVal(_T("class"),&classValue) + && node->GetPropVal(_T("name"),&nameValue)){ + + aXRCWndClassData.Add( + XRCWndClassData(nameValue,classValue,node) + ); + } + node = node -> GetNext(); + } + } wxString internalName = GetInternalFileName(parFiles[i], flist); doc.Save(parOutputPath + wxFILE_SEP_PATH + internalName); @@ -362,7 +486,6 @@ void XmlResApp::MakePackageZIP(const wxArrayString& flist) - static wxString FileToCppArray(wxString filename, int num) { wxString output; @@ -467,6 +590,28 @@ _T("\n")); } +void XmlResApp::GenCPPHeader() +{ + wxString fileSpec = (parOutput.BeforeLast('.')).AfterLast('/'); + wxString heaFileName = fileSpec + _T(".h"); + + wxFFile file(heaFileName, wxT("wt")); + file.Write( +_T("//\n") +_T("// This file was automatically generated by wxrc, do not edit by hand.\n") +_T("//\n\n") +_T("#ifndef __") + fileSpec + _T("_h__\n") +_T("#define __") + fileSpec + _T("_h__\n") +); + for(size_t i=0;i +% \section{XML-based resource system overview}\label{xrcoverview} Classes: \helpref{wxXmlResource}{wxxmlresource}, \helpref{wxXmlResourceHandler}{wxxmlresourcehandler} @@ -112,6 +115,8 @@ To compile binary resource files, use the command-line wxrc utility. It takes on \item -h (--help): show a help message \item -v (--verbose): show verbose logging information \item -c (--cpp-code): write C++ source rather than a XRS file +\item -e (--extra-cpp-code): if used together with -c, generates C++ header file +containing class definitions for the windows defined by the XRC file (see special subsection) \item -u (--uncompressed): do not compress XML files (C++ only) \item -g (--gettext): output .po catalog (to stdout, or a file if -o is used) \item -n (--function) : specify C++ function name (use with -c) @@ -448,6 +453,95 @@ This is the XML file (resource.xrc) for the XRC sample. Please see Technical Note 14 (docs/tech/tn0014.txt) in your wxWindows distribution. +\subsection{C++ header file generation}\label{xrccppheader} + +Using the {\tt -e} switch together with {\tt -c}, a C++ header file is written +containing class definitions for the GUI windows defined in the XRC file. +This code generation can make it easier to use XRC and automate program +development. +The classes can be used as basis for development, freeing the +programmer from dealing with most of the XRC specifities (e.g. {\tt XRCCTRL}). + +For each top level window defined in the XRC file a C++ class definition is +generated, containing as class members the named widgets of the window. +A default constructor for each class is also generated. Inside the constructor +all XRC loading is done and all class members representing widgets are initialized. + +A simple example will help understand how the scheme works. Suppose you have +a XRC file defining a top level window {\tt TestWnd\_Base}, which subclasses {\tt wxFrame} (any +other class like {\tt wxDialog} will do also), and has subwidgets {\tt wxTextCtrl} A and {\tt wxButton} B. +The XRC file and corresponding class definition in the header file will be something like: + +\begin{verbatim} + + + + -1,-1 + Test + + wxHORIZONTAL + + + + + + + + + + + + + + + +class TestWnd_Base : public wxFrame { +protected: + wxTextCtrl* A; + wxButton* B; + +private: + void InitWidgetsFromXRC(){ + wxXmlResource::Get()->LoadObject(this,NULL,"TestWnd","wxFrame"); + A = XRCCTRL(*this,"A",wxTextCtrl); + B = XRCCTRL(*this,"B",wxButton); + } +public: +TestWnd::TestWnd(){ + InitWidgetsFromXRC(); + } +}; +\end{verbatim} + +The generated window class can be used as basis for the full window class. The +class members which represent widgets may be accessed by name instead of using +{\tt XRCCTRL} every time you wish to reference them (note that they are {\tt protected} class members), +though you must still use {\tt XRCID} to refer to widget ids in the event +table. + +Example: +\begin{verbatim} +#include "resource.h" + +class TestWnd : public TestWnd_Base { + public: + TestWnd(){ + // A, B already initialised at this point + A->SetValue("Updated in TestWnd::TestWnd"); + B->SetValue("Nice :)"); + } + void OnBPressed(wxEvent& event){ + Close(); + } + DECLARE_EVENT_TABLE(); +}; + +BEGIN_EVENT_TABLE(TestWnd,TestWnd_Base) +EVT_BUTTON(XRCID("B"),TestWnd::OnBPressed) +END_EVENT_TABLE() + +\end{verbatim} + \subsection{Adding new resource handlers}\label{newresourcehandlers} Coming soon. diff --git a/utils/wxrc/wxrc.cpp b/utils/wxrc/wxrc.cpp index 79362762e1..bc4a9df795 100644 --- a/utils/wxrc/wxrc.cpp +++ b/utils/wxrc/wxrc.cpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // Name: wxrc.cpp // Purpose: XML resource compiler -// Author: Vaclav Slavik +// Author: Vaclav Slavik, Eduardo Marques // Created: 2000/03/05 // RCS-ID: $Id$ // Copyright: (c) 2000 Vaclav Slavik @@ -33,16 +33,112 @@ #include "wx/wfstream.h" +class XRCWidgetData +{ +public: + XRCWidgetData(const wxString& vname,const wxString& vclass) + : m_class(vclass), m_name(vname) {} + const wxString& GetName() const { return m_name; } + const wxString& GetClass() const { return m_class; } +private: + wxString m_class; + wxString m_name; +}; +#include "wx/arrimpl.cpp" +WX_DECLARE_OBJARRAY(XRCWidgetData,ArrayOfXRCWidgetData); +WX_DEFINE_OBJARRAY(ArrayOfXRCWidgetData); + +class XRCWndClassData +{ +private: + wxString m_className; + wxString m_parentClassName; + ArrayOfXRCWidgetData m_wdata; + + void BrowseXmlNode(wxXmlNode* node) + { + wxString classValue; + wxString nameValue; + wxXmlNode* children; + while (node) + { + if (node->GetName() == _T("object") + && node->GetPropVal(_T("class"),&classValue) + && node->GetPropVal(_T("name"),&nameValue)) + { + m_wdata.Add(XRCWidgetData(nameValue,classValue)); + } + children = node->GetChildren(); + if (children) + BrowseXmlNode(children); + node = node->GetNext(); + } + } + +public: + XRCWndClassData(const wxString& className,const wxString& parentClassName, const wxXmlNode* node) : + m_className(className) , m_parentClassName(parentClassName) { + + BrowseXmlNode(node->GetChildren()); + + } + + const ArrayOfXRCWidgetData& GetWidgetData(){ + return m_wdata; + } + void GenerateHeaderCode(wxFFile& file){ + + file.Write(_T("class ") + m_className + _T(" : public ") + m_parentClassName + + _T(" {\nprotected:\n")); + for(size_t i=0;iLoadObject(this,NULL,\"") + + m_className + + +_T("\",\"") + + m_parentClassName + + _T("\");\n")); + for(size_t i=0;iGetChildren(); + wxString classValue,nameValue; + while(node){ + if(node->GetName() == _T("object") + && node->GetPropVal(_T("class"),&classValue) + && node->GetPropVal(_T("name"),&nameValue)){ + + aXRCWndClassData.Add( + XRCWndClassData(nameValue,classValue,node) + ); + } + node = node -> GetNext(); + } + } wxString internalName = GetInternalFileName(parFiles[i], flist); doc.Save(parOutputPath + wxFILE_SEP_PATH + internalName); @@ -362,7 +486,6 @@ void XmlResApp::MakePackageZIP(const wxArrayString& flist) - static wxString FileToCppArray(wxString filename, int num) { wxString output; @@ -467,6 +590,28 @@ _T("\n")); } +void XmlResApp::GenCPPHeader() +{ + wxString fileSpec = (parOutput.BeforeLast('.')).AfterLast('/'); + wxString heaFileName = fileSpec + _T(".h"); + + wxFFile file(heaFileName, wxT("wt")); + file.Write( +_T("//\n") +_T("// This file was automatically generated by wxrc, do not edit by hand.\n") +_T("//\n\n") +_T("#ifndef __") + fileSpec + _T("_h__\n") +_T("#define __") + fileSpec + _T("_h__\n") +); + for(size_t i=0;i