Add wxXmlResource::LoadObjectRecursively().
These methods can be used to load objects from anywhere in the XRC resource tree and not just from the top level. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@61934 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -413,6 +413,7 @@ All (GUI):
|
|||||||
- wxPropertyGrid: added wxPG_NO_INTERNAL_BORDER, wxPG_EX_NO_TOOLBAR_DIVIDER
|
- wxPropertyGrid: added wxPG_NO_INTERNAL_BORDER, wxPG_EX_NO_TOOLBAR_DIVIDER
|
||||||
and wxPG_EX_TOOLBAR_SEPARATOR styles for finer control over borders.
|
and wxPG_EX_TOOLBAR_SEPARATOR styles for finer control over borders.
|
||||||
Borders around property grid are now native for consistency.
|
Borders around property grid are now native for consistency.
|
||||||
|
- Added wxXmlResource::LoadObjectRecursively().
|
||||||
|
|
||||||
GTK:
|
GTK:
|
||||||
|
|
||||||
|
@@ -188,13 +188,40 @@ public:
|
|||||||
// Load an object from the resource specifying both the resource name and
|
// Load an object from the resource specifying both the resource name and
|
||||||
// the classname. This lets you load nonstandard container windows.
|
// the classname. This lets you load nonstandard container windows.
|
||||||
wxObject *LoadObject(wxWindow *parent, const wxString& name,
|
wxObject *LoadObject(wxWindow *parent, const wxString& name,
|
||||||
const wxString& classname);
|
const wxString& classname)
|
||||||
|
{
|
||||||
|
return DoLoadObject(parent, name, classname, false /* !recursive */);
|
||||||
|
}
|
||||||
|
|
||||||
// Load an object from the resource specifying both the resource name and
|
// Load an object from the resource specifying both the resource name and
|
||||||
// the classname. This form lets you finish the creation of an existing
|
// the classname. This form lets you finish the creation of an existing
|
||||||
// instance.
|
// instance.
|
||||||
bool LoadObject(wxObject *instance, wxWindow *parent, const wxString& name,
|
bool LoadObject(wxObject *instance,
|
||||||
const wxString& classname);
|
wxWindow *parent,
|
||||||
|
const wxString& name,
|
||||||
|
const wxString& classname)
|
||||||
|
{
|
||||||
|
return DoLoadObject(instance, parent, name, classname, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// These versions of LoadObject() look for the object with the given name
|
||||||
|
// recursively (breadth first) and can be used to instantiate an individual
|
||||||
|
// control defined anywhere in an XRC file. No check is done that the name
|
||||||
|
// is unique, it's up to the caller to ensure this.
|
||||||
|
wxObject *LoadObjectRecursively(wxWindow *parent,
|
||||||
|
const wxString& name,
|
||||||
|
const wxString& classname)
|
||||||
|
{
|
||||||
|
return DoLoadObject(parent, name, classname, true /* recursive */);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LoadObjectRecursively(wxObject *instance,
|
||||||
|
wxWindow *parent,
|
||||||
|
const wxString& name,
|
||||||
|
const wxString& classname)
|
||||||
|
{
|
||||||
|
return DoLoadObject(instance, parent, name, classname, true);
|
||||||
|
}
|
||||||
|
|
||||||
// Loads a bitmap resource from a file.
|
// Loads a bitmap resource from a file.
|
||||||
wxBitmap LoadBitmap(const wxString& name);
|
wxBitmap LoadBitmap(const wxString& name);
|
||||||
@@ -309,7 +336,11 @@ protected:
|
|||||||
// (Uses only 'handlerToUse' if != NULL)
|
// (Uses only 'handlerToUse' if != NULL)
|
||||||
wxObject *CreateResFromNode(wxXmlNode *node, wxObject *parent,
|
wxObject *CreateResFromNode(wxXmlNode *node, wxObject *parent,
|
||||||
wxObject *instance = NULL,
|
wxObject *instance = NULL,
|
||||||
wxXmlResourceHandler *handlerToUse = NULL);
|
wxXmlResourceHandler *handlerToUse = NULL)
|
||||||
|
{
|
||||||
|
return node ? DoCreateResFromNode(*node, parent, instance, handlerToUse)
|
||||||
|
: NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// Helper of Load() and Unload(): returns the URL corresponding to the
|
// Helper of Load() and Unload(): returns the URL corresponding to the
|
||||||
// given file if it's indeed a file, otherwise returns the original string
|
// given file if it's indeed a file, otherwise returns the original string
|
||||||
@@ -326,6 +357,24 @@ private:
|
|||||||
wxXmlResourceDataRecords& Data() { return *m_data; }
|
wxXmlResourceDataRecords& Data() { return *m_data; }
|
||||||
const wxXmlResourceDataRecords& Data() const { return *m_data; }
|
const wxXmlResourceDataRecords& Data() const { return *m_data; }
|
||||||
|
|
||||||
|
// the real implementation of CreateResFromNode(): this should be only
|
||||||
|
// called if node is non-NULL
|
||||||
|
wxObject *DoCreateResFromNode(wxXmlNode& node,
|
||||||
|
wxObject *parent,
|
||||||
|
wxObject *instance,
|
||||||
|
wxXmlResourceHandler *handlerToUse = NULL);
|
||||||
|
|
||||||
|
// common part of LoadObject() and LoadObjectRecursively()
|
||||||
|
wxObject *DoLoadObject(wxWindow *parent,
|
||||||
|
const wxString& name,
|
||||||
|
const wxString& classname,
|
||||||
|
bool recursive);
|
||||||
|
bool DoLoadObject(wxObject *instance,
|
||||||
|
wxWindow *parent,
|
||||||
|
const wxString& name,
|
||||||
|
const wxString& classname,
|
||||||
|
bool recursive);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
long m_version;
|
long m_version;
|
||||||
|
|
||||||
|
@@ -286,6 +286,10 @@ public:
|
|||||||
The first overload lets you load nonstandard container windows and returns
|
The first overload lets you load nonstandard container windows and returns
|
||||||
@NULL on failure. The second one lets you finish the creation of an existing
|
@NULL on failure. The second one lets you finish the creation of an existing
|
||||||
instance and returns @false on failure.
|
instance and returns @false on failure.
|
||||||
|
|
||||||
|
In either case, only the resources defined at the top level of XRC
|
||||||
|
files can be loaded by this function, use LoadObjectRecursively() if
|
||||||
|
you need to load an object defined deeper in the hierarchy.
|
||||||
*/
|
*/
|
||||||
wxObject* LoadObject(wxWindow* parent, const wxString& name,
|
wxObject* LoadObject(wxWindow* parent, const wxString& name,
|
||||||
const wxString& classname);
|
const wxString& classname);
|
||||||
@@ -294,6 +298,27 @@ public:
|
|||||||
const wxString& classname);
|
const wxString& classname);
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
|
//@{
|
||||||
|
/**
|
||||||
|
Load an object from anywhere in the resource tree.
|
||||||
|
|
||||||
|
These methods are similar to LoadObject() but may be used to load an
|
||||||
|
object from anywhere in the resource tree and not only the top level.
|
||||||
|
Note that you will very rarely need to do this as in normal use the
|
||||||
|
entire container window (defined at the top level) is loaded and not
|
||||||
|
its individual children but this method can be useful in some
|
||||||
|
particular situations.
|
||||||
|
|
||||||
|
@since 2.9.1
|
||||||
|
*/
|
||||||
|
wxObject* LoadObjectRecursively(wxWindow* parent,
|
||||||
|
const wxString& name,
|
||||||
|
const wxString& classname);
|
||||||
|
bool LoadObjectRecursively(wxObject* instance, wxWindow* parent,
|
||||||
|
const wxString& name,
|
||||||
|
const wxString& classname);
|
||||||
|
//@}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Loads a panel. @a parent points to the parent window.
|
Loads a panel. @a parent points to the parent window.
|
||||||
*/
|
*/
|
||||||
|
@@ -87,6 +87,7 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame)
|
|||||||
EVT_MENU(XRCID("platform_property_tool_or_menuitem"), MyFrame::OnPlatformPropertyToolOrMenuCommand)
|
EVT_MENU(XRCID("platform_property_tool_or_menuitem"), MyFrame::OnPlatformPropertyToolOrMenuCommand)
|
||||||
EVT_MENU(XRCID("art_provider_tool_or_menuitem"), MyFrame::OnArtProviderToolOrMenuCommand)
|
EVT_MENU(XRCID("art_provider_tool_or_menuitem"), MyFrame::OnArtProviderToolOrMenuCommand)
|
||||||
EVT_MENU(XRCID("variable_expansion_tool_or_menuitem"), MyFrame::OnVariableExpansionToolOrMenuCommand)
|
EVT_MENU(XRCID("variable_expansion_tool_or_menuitem"), MyFrame::OnVariableExpansionToolOrMenuCommand)
|
||||||
|
EVT_MENU(XRCID("recursive_load"), MyFrame::OnRecursiveLoad)
|
||||||
EVT_MENU(wxID_ABOUT, MyFrame::OnAboutToolOrMenuCommand)
|
EVT_MENU(wxID_ABOUT, MyFrame::OnAboutToolOrMenuCommand)
|
||||||
END_EVENT_TABLE()
|
END_EVENT_TABLE()
|
||||||
|
|
||||||
@@ -311,6 +312,47 @@ void MyFrame::OnVariableExpansionToolOrMenuCommand(wxCommandEvent& WXUNUSED(even
|
|||||||
dlg.ShowModal();
|
dlg.ShowModal();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MyFrame::OnRecursiveLoad(wxCommandEvent& WXUNUSED(event))
|
||||||
|
{
|
||||||
|
// this dialog is created manually to show how you can inject a single
|
||||||
|
// control from XRC into an existing dialog
|
||||||
|
//
|
||||||
|
// this is a slightly contrived example, please keep in mind that it's done
|
||||||
|
// only to demonstrate LoadObjectRecursively() in action and is not the
|
||||||
|
// recommended to do this
|
||||||
|
wxDialog dlg(NULL, wxID_ANY, "Recursive Load Example",
|
||||||
|
wxDefaultPosition, wxDefaultSize,
|
||||||
|
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER);
|
||||||
|
wxSizer * const sizer = new wxBoxSizer(wxVERTICAL);
|
||||||
|
sizer->Add
|
||||||
|
(
|
||||||
|
new wxStaticText
|
||||||
|
(
|
||||||
|
&dlg,
|
||||||
|
wxID_ANY,
|
||||||
|
"The entire tree book control below is loaded from XRC"
|
||||||
|
),
|
||||||
|
wxSizerFlags().Expand().Border()
|
||||||
|
);
|
||||||
|
|
||||||
|
sizer->Add
|
||||||
|
(
|
||||||
|
static_cast<wxWindow *>
|
||||||
|
(
|
||||||
|
// notice that controls_treebook is defined inside a notebook page
|
||||||
|
// inside a dialog defined in controls.xrc and so LoadObject()
|
||||||
|
// wouldn't find it -- but LoadObjectRecursively() does
|
||||||
|
wxXmlResource::Get()->
|
||||||
|
LoadObjectRecursively(&dlg, "controls_treebook", "wxTreebook")
|
||||||
|
),
|
||||||
|
wxSizerFlags(1).Expand().Border()
|
||||||
|
);
|
||||||
|
|
||||||
|
dlg.SetSizer(sizer);
|
||||||
|
dlg.SetClientSize(400, 200);
|
||||||
|
|
||||||
|
dlg.ShowModal();
|
||||||
|
}
|
||||||
|
|
||||||
void MyFrame::OnAboutToolOrMenuCommand(wxCommandEvent& WXUNUSED(event))
|
void MyFrame::OnAboutToolOrMenuCommand(wxCommandEvent& WXUNUSED(event))
|
||||||
{
|
{
|
||||||
|
@@ -48,6 +48,7 @@ private:
|
|||||||
void OnPlatformPropertyToolOrMenuCommand(wxCommandEvent& event);
|
void OnPlatformPropertyToolOrMenuCommand(wxCommandEvent& event);
|
||||||
void OnArtProviderToolOrMenuCommand(wxCommandEvent& event);
|
void OnArtProviderToolOrMenuCommand(wxCommandEvent& event);
|
||||||
void OnVariableExpansionToolOrMenuCommand(wxCommandEvent& event);
|
void OnVariableExpansionToolOrMenuCommand(wxCommandEvent& event);
|
||||||
|
void OnRecursiveLoad(wxCommandEvent& event);
|
||||||
void OnAnimationCtrlPlay(wxCommandEvent& event);
|
void OnAnimationCtrlPlay(wxCommandEvent& event);
|
||||||
|
|
||||||
// Any class wishing to process wxWidgets events must use this macro
|
// Any class wishing to process wxWidgets events must use this macro
|
||||||
|
@@ -69,6 +69,10 @@
|
|||||||
<bitmap>variable.xpm</bitmap>
|
<bitmap>variable.xpm</bitmap>
|
||||||
<help>Replace variables in the XRC file at runtime</help>
|
<help>Replace variables in the XRC file at runtime</help>
|
||||||
</object>
|
</object>
|
||||||
|
<object class="wxMenuItem" name="recursive_load">
|
||||||
|
<label>_Recursive Load</label>
|
||||||
|
<help>Show how an individual control can be loaded</help>
|
||||||
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<object class="wxMenu" name="help_menu">
|
<object class="wxMenu" name="help_menu">
|
||||||
<label>_Help</label>
|
<label>_Help</label>
|
||||||
|
@@ -431,14 +431,27 @@ wxIcon wxXmlResource::LoadIcon(const wxString& name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
wxObject *wxXmlResource::LoadObject(wxWindow *parent, const wxString& name, const wxString& classname)
|
wxObject *
|
||||||
|
wxXmlResource::DoLoadObject(wxWindow *parent,
|
||||||
|
const wxString& name,
|
||||||
|
const wxString& classname,
|
||||||
|
bool recursive)
|
||||||
{
|
{
|
||||||
return CreateResFromNode(FindResource(name, classname), parent, NULL);
|
wxXmlNode * const node = FindResource(name, classname, recursive);
|
||||||
|
|
||||||
|
return node ? DoCreateResFromNode(*node, parent, NULL) : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxXmlResource::LoadObject(wxObject *instance, wxWindow *parent, const wxString& name, const wxString& classname)
|
bool
|
||||||
|
wxXmlResource::DoLoadObject(wxObject *instance,
|
||||||
|
wxWindow *parent,
|
||||||
|
const wxString& name,
|
||||||
|
const wxString& classname,
|
||||||
|
bool recursive)
|
||||||
{
|
{
|
||||||
return CreateResFromNode(FindResource(name, classname), parent, instance) != NULL;
|
wxXmlNode * const node = FindResource(name, classname, recursive);
|
||||||
|
|
||||||
|
return node && DoCreateResFromNode(*node, parent, instance) != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -819,23 +832,23 @@ static void MergeNodesOver(wxXmlNode& dest, wxXmlNode& overwriteWith,
|
|||||||
dest.SetContent(overwriteWith.GetContent());
|
dest.SetContent(overwriteWith.GetContent());
|
||||||
}
|
}
|
||||||
|
|
||||||
wxObject *wxXmlResource::CreateResFromNode(wxXmlNode *node, wxObject *parent,
|
wxObject *
|
||||||
wxObject *instance,
|
wxXmlResource::DoCreateResFromNode(wxXmlNode& node,
|
||||||
wxXmlResourceHandler *handlerToUse)
|
wxObject *parent,
|
||||||
|
wxObject *instance,
|
||||||
|
wxXmlResourceHandler *handlerToUse)
|
||||||
{
|
{
|
||||||
if (node == NULL) return NULL;
|
|
||||||
|
|
||||||
// handling of referenced resource
|
// handling of referenced resource
|
||||||
if ( node->GetName() == wxT("object_ref") )
|
if ( node.GetName() == wxT("object_ref") )
|
||||||
{
|
{
|
||||||
wxString refName = node->GetAttribute(wxT("ref"), wxEmptyString);
|
wxString refName = node.GetAttribute(wxT("ref"), wxEmptyString);
|
||||||
wxXmlNode* refNode = FindResource(refName, wxEmptyString, true);
|
wxXmlNode* refNode = FindResource(refName, wxEmptyString, true);
|
||||||
|
|
||||||
if ( !refNode )
|
if ( !refNode )
|
||||||
{
|
{
|
||||||
ReportError
|
ReportError
|
||||||
(
|
(
|
||||||
node,
|
&node,
|
||||||
wxString::Format
|
wxString::Format
|
||||||
(
|
(
|
||||||
"referenced object node with ref=\"%s\" not found",
|
"referenced object node with ref=\"%s\" not found",
|
||||||
@@ -845,14 +858,14 @@ wxObject *wxXmlResource::CreateResFromNode(wxXmlNode *node, wxObject *parent,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !node->GetChildren() )
|
if ( !node.GetChildren() )
|
||||||
{
|
{
|
||||||
// In the typical, simple case, <object_ref> is used to link
|
// In the typical, simple case, <object_ref> is used to link
|
||||||
// to another node and doesn't have any content of its own that
|
// to another node and doesn't have any content of its own that
|
||||||
// would overwrite linked object's properties. In this case,
|
// would overwrite linked object's properties. In this case,
|
||||||
// we can simply create the resource from linked node.
|
// we can simply create the resource from linked node.
|
||||||
|
|
||||||
return CreateResFromNode(refNode, parent, instance);
|
return DoCreateResFromNode(*refNode, parent, instance);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -862,42 +875,42 @@ wxObject *wxXmlResource::CreateResFromNode(wxXmlNode *node, wxObject *parent,
|
|||||||
// load the resource from result of the merge.
|
// load the resource from result of the merge.
|
||||||
|
|
||||||
wxXmlNode copy(*refNode);
|
wxXmlNode copy(*refNode);
|
||||||
MergeNodesOver(copy, *node, GetFileNameFromNode(node, Data()));
|
MergeNodesOver(copy, node, GetFileNameFromNode(&node, Data()));
|
||||||
|
|
||||||
// remember referenced object's file, see GetFileNameFromNode()
|
// remember referenced object's file, see GetFileNameFromNode()
|
||||||
copy.AddAttribute(ATTR_INPUT_FILENAME,
|
copy.AddAttribute(ATTR_INPUT_FILENAME,
|
||||||
GetFileNameFromNode(refNode, Data()));
|
GetFileNameFromNode(refNode, Data()));
|
||||||
|
|
||||||
return CreateResFromNode(©, parent, instance);
|
return DoCreateResFromNode(copy, parent, instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handlerToUse)
|
if (handlerToUse)
|
||||||
{
|
{
|
||||||
if (handlerToUse->CanHandle(node))
|
if (handlerToUse->CanHandle(&node))
|
||||||
{
|
{
|
||||||
return handlerToUse->CreateResource(node, parent, instance);
|
return handlerToUse->CreateResource(&node, parent, instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (node->GetName() == wxT("object"))
|
else if (node.GetName() == wxT("object"))
|
||||||
{
|
{
|
||||||
for ( wxVector<wxXmlResourceHandler*>::iterator h = m_handlers.begin();
|
for ( wxVector<wxXmlResourceHandler*>::iterator h = m_handlers.begin();
|
||||||
h != m_handlers.end(); ++h )
|
h != m_handlers.end(); ++h )
|
||||||
{
|
{
|
||||||
wxXmlResourceHandler *handler = *h;
|
wxXmlResourceHandler *handler = *h;
|
||||||
if (handler->CanHandle(node))
|
if (handler->CanHandle(&node))
|
||||||
return handler->CreateResource(node, parent, instance);
|
return handler->CreateResource(&node, parent, instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReportError
|
ReportError
|
||||||
(
|
(
|
||||||
node,
|
&node,
|
||||||
wxString::Format
|
wxString::Format
|
||||||
(
|
(
|
||||||
"no handler found for XML node \"%s\" (class \"%s\")",
|
"no handler found for XML node \"%s\" (class \"%s\")",
|
||||||
node->GetName(),
|
node.GetName(),
|
||||||
node->GetAttribute("class", wxEmptyString)
|
node.GetAttribute("class", wxEmptyString)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -1883,8 +1896,8 @@ void wxXmlResourceHandler::CreateChildren(wxObject *parent, bool this_hnd_only)
|
|||||||
{
|
{
|
||||||
if ( IsObjectNode(n) )
|
if ( IsObjectNode(n) )
|
||||||
{
|
{
|
||||||
m_resource->CreateResFromNode(n, parent, NULL,
|
m_resource->DoCreateResFromNode(*n, parent, NULL,
|
||||||
this_hnd_only ? this : NULL);
|
this_hnd_only ? this : NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user