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
|
||||
and wxPG_EX_TOOLBAR_SEPARATOR styles for finer control over borders.
|
||||
Borders around property grid are now native for consistency.
|
||||
- Added wxXmlResource::LoadObjectRecursively().
|
||||
|
||||
GTK:
|
||||
|
||||
|
@@ -188,13 +188,40 @@ public:
|
||||
// Load an object from the resource specifying both the resource name and
|
||||
// the classname. This lets you load nonstandard container windows.
|
||||
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
|
||||
// the classname. This form lets you finish the creation of an existing
|
||||
// instance.
|
||||
bool LoadObject(wxObject *instance, wxWindow *parent, const wxString& name,
|
||||
const wxString& classname);
|
||||
bool LoadObject(wxObject *instance,
|
||||
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.
|
||||
wxBitmap LoadBitmap(const wxString& name);
|
||||
@@ -309,7 +336,11 @@ protected:
|
||||
// (Uses only 'handlerToUse' if != NULL)
|
||||
wxObject *CreateResFromNode(wxXmlNode *node, wxObject *parent,
|
||||
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
|
||||
// given file if it's indeed a file, otherwise returns the original string
|
||||
@@ -326,6 +357,24 @@ private:
|
||||
wxXmlResourceDataRecords& Data() { 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:
|
||||
long m_version;
|
||||
|
||||
|
@@ -286,6 +286,10 @@ public:
|
||||
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
|
||||
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,
|
||||
const wxString& classname);
|
||||
@@ -294,6 +298,27 @@ public:
|
||||
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.
|
||||
*/
|
||||
|
@@ -87,6 +87,7 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame)
|
||||
EVT_MENU(XRCID("platform_property_tool_or_menuitem"), MyFrame::OnPlatformPropertyToolOrMenuCommand)
|
||||
EVT_MENU(XRCID("art_provider_tool_or_menuitem"), MyFrame::OnArtProviderToolOrMenuCommand)
|
||||
EVT_MENU(XRCID("variable_expansion_tool_or_menuitem"), MyFrame::OnVariableExpansionToolOrMenuCommand)
|
||||
EVT_MENU(XRCID("recursive_load"), MyFrame::OnRecursiveLoad)
|
||||
EVT_MENU(wxID_ABOUT, MyFrame::OnAboutToolOrMenuCommand)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
@@ -311,6 +312,47 @@ void MyFrame::OnVariableExpansionToolOrMenuCommand(wxCommandEvent& WXUNUSED(even
|
||||
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))
|
||||
{
|
||||
|
@@ -48,6 +48,7 @@ private:
|
||||
void OnPlatformPropertyToolOrMenuCommand(wxCommandEvent& event);
|
||||
void OnArtProviderToolOrMenuCommand(wxCommandEvent& event);
|
||||
void OnVariableExpansionToolOrMenuCommand(wxCommandEvent& event);
|
||||
void OnRecursiveLoad(wxCommandEvent& event);
|
||||
void OnAnimationCtrlPlay(wxCommandEvent& event);
|
||||
|
||||
// Any class wishing to process wxWidgets events must use this macro
|
||||
|
@@ -69,6 +69,10 @@
|
||||
<bitmap>variable.xpm</bitmap>
|
||||
<help>Replace variables in the XRC file at runtime</help>
|
||||
</object>
|
||||
<object class="wxMenuItem" name="recursive_load">
|
||||
<label>_Recursive Load</label>
|
||||
<help>Show how an individual control can be loaded</help>
|
||||
</object>
|
||||
</object>
|
||||
<object class="wxMenu" name="help_menu">
|
||||
<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());
|
||||
}
|
||||
|
||||
wxObject *wxXmlResource::CreateResFromNode(wxXmlNode *node, wxObject *parent,
|
||||
wxObject *
|
||||
wxXmlResource::DoCreateResFromNode(wxXmlNode& node,
|
||||
wxObject *parent,
|
||||
wxObject *instance,
|
||||
wxXmlResourceHandler *handlerToUse)
|
||||
{
|
||||
if (node == NULL) return NULL;
|
||||
|
||||
// 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);
|
||||
|
||||
if ( !refNode )
|
||||
{
|
||||
ReportError
|
||||
(
|
||||
node,
|
||||
&node,
|
||||
wxString::Format
|
||||
(
|
||||
"referenced object node with ref=\"%s\" not found",
|
||||
@@ -845,14 +858,14 @@ wxObject *wxXmlResource::CreateResFromNode(wxXmlNode *node, wxObject *parent,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( !node->GetChildren() )
|
||||
if ( !node.GetChildren() )
|
||||
{
|
||||
// In the typical, simple case, <object_ref> is used to link
|
||||
// to another node and doesn't have any content of its own that
|
||||
// would overwrite linked object's properties. In this case,
|
||||
// we can simply create the resource from linked node.
|
||||
|
||||
return CreateResFromNode(refNode, parent, instance);
|
||||
return DoCreateResFromNode(*refNode, parent, instance);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -862,42 +875,42 @@ wxObject *wxXmlResource::CreateResFromNode(wxXmlNode *node, wxObject *parent,
|
||||
// load the resource from result of the merge.
|
||||
|
||||
wxXmlNode copy(*refNode);
|
||||
MergeNodesOver(copy, *node, GetFileNameFromNode(node, Data()));
|
||||
MergeNodesOver(copy, node, GetFileNameFromNode(&node, Data()));
|
||||
|
||||
// remember referenced object's file, see GetFileNameFromNode()
|
||||
copy.AddAttribute(ATTR_INPUT_FILENAME,
|
||||
GetFileNameFromNode(refNode, Data()));
|
||||
|
||||
return CreateResFromNode(©, parent, instance);
|
||||
return DoCreateResFromNode(copy, parent, instance);
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
h != m_handlers.end(); ++h )
|
||||
{
|
||||
wxXmlResourceHandler *handler = *h;
|
||||
if (handler->CanHandle(node))
|
||||
return handler->CreateResource(node, parent, instance);
|
||||
if (handler->CanHandle(&node))
|
||||
return handler->CreateResource(&node, parent, instance);
|
||||
}
|
||||
}
|
||||
|
||||
ReportError
|
||||
(
|
||||
node,
|
||||
&node,
|
||||
wxString::Format
|
||||
(
|
||||
"no handler found for XML node \"%s\" (class \"%s\")",
|
||||
node->GetName(),
|
||||
node->GetAttribute("class", wxEmptyString)
|
||||
node.GetName(),
|
||||
node.GetAttribute("class", wxEmptyString)
|
||||
)
|
||||
);
|
||||
return NULL;
|
||||
@@ -1883,7 +1896,7 @@ void wxXmlResourceHandler::CreateChildren(wxObject *parent, bool this_hnd_only)
|
||||
{
|
||||
if ( IsObjectNode(n) )
|
||||
{
|
||||
m_resource->CreateResFromNode(n, parent, NULL,
|
||||
m_resource->DoCreateResFromNode(*n, parent, NULL,
|
||||
this_hnd_only ? this : NULL);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user