wxwidgets/src/xrc/xh_propgrid.cpp
Vadim Zeitlin 9550c37e29 Support inherited attributes in wxPropertyGrid XRC handler
Allow specifying recurse="1" to inherit the attribute, as this is much
nicer than having to specify it for all the children.

Also add support for this to wxPropertyGridPopulator, which is used by
the XRC handler.
2024-02-03 21:46:15 +01:00

297 lines
8.2 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// Name: xh_propgrid.cpp
// Purpose: XRC resource for wxPropertyGrid
// Author: Jaakko Salli
// Created: May-16-2007
// Copyright: (c) 2007 Jaakko Salli
// Licence: wxWindows license
/////////////////////////////////////////////////////////////////////////////
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#if wxUSE_XRC && wxUSE_PROPGRID
#include "wx/xrc/xh_propgrid.h"
#include "wx/propgrid/manager.h"
#include "wx/propgrid/propgrid.h"
#include "wx/xml/xml.h"
#ifndef WX_PRECOMP
#include "wx/intl.h"
#endif
IMPLEMENT_DYNAMIC_CLASS(wxPropertyGridXmlHandler, wxXmlResourceHandler)
wxPropertyGridXmlHandler::wxPropertyGridXmlHandler()
:wxXmlResourceHandler()
{
XRC_ADD_STYLE(wxTAB_TRAVERSAL);
XRC_ADD_STYLE(wxPG_AUTO_SORT);
XRC_ADD_STYLE(wxPG_HIDE_CATEGORIES);
XRC_ADD_STYLE(wxPG_BOLD_MODIFIED);
XRC_ADD_STYLE(wxPG_SPLITTER_AUTO_CENTER);
XRC_ADD_STYLE(wxPG_TOOLTIPS);
XRC_ADD_STYLE(wxPG_HIDE_MARGIN);
XRC_ADD_STYLE(wxPG_STATIC_SPLITTER);
XRC_ADD_STYLE(wxPG_LIMITED_EDITING);
XRC_ADD_STYLE(wxPG_TOOLBAR);
XRC_ADD_STYLE(wxPG_DESCRIPTION);
XRC_ADD_STYLE(wxPG_EX_INIT_NOCAT);
XRC_ADD_STYLE(wxPG_EX_HELP_AS_TOOLTIPS);
XRC_ADD_STYLE(wxPG_EX_AUTO_UNSPECIFIED_VALUES);
XRC_ADD_STYLE(wxPG_EX_WRITEONLY_BUILTIN_ATTRIBUTES);
XRC_ADD_STYLE(wxPG_EX_NO_FLAT_TOOLBAR);
XRC_ADD_STYLE(wxPG_EX_MODE_BUTTONS);
AddWindowStyles();
}
class wxPropertyGridXrcPopulator : public wxPropertyGridPopulator
{
public:
wxPropertyGridXrcPopulator( wxPropertyGridXmlHandler* handler )
: wxPropertyGridPopulator()
{
m_xrcHandler = handler;
m_prevPopulator = m_xrcHandler->m_populator;
}
~wxPropertyGridXrcPopulator() override
{
m_xrcHandler->m_populator = m_prevPopulator;
}
void DoScanForChildren() override
{
m_xrcHandler->CreateChildrenPrivately(m_pg, nullptr);
}
protected:
wxPropertyGridXmlHandler* m_xrcHandler;
wxPropertyGridPopulator* m_prevPopulator;
};
void wxPropertyGridXmlHandler::InitPopulator()
{
wxPropertyGridXrcPopulator* populator
= new wxPropertyGridXrcPopulator(this);
m_populator = populator;
}
void wxPropertyGridXmlHandler::PopulatePage( wxPropertyGridPageState* state )
{
wxString sColumns(wxT("columns"));
if ( HasParam(sColumns) )
state->SetColumnCount( GetLong(sColumns) );
m_populator->SetState( state );
m_populator->AddChildren( state->DoGetRoot() );
}
void wxPropertyGridXmlHandler::DonePopulator()
{
delete m_populator;
}
void wxPropertyGridXmlHandler::HandlePropertyGridParams()
{
wxString sVW(wxT("virtualwidth"));
if ( HasParam(sVW) )
{
m_pg->SetVirtualWidth(GetDimension(sVW));
}
}
wxObject *wxPropertyGridXmlHandler::DoCreateResource()
{
const wxXmlNode* node = m_node;
wxString nodeName = node->GetName();
if ( nodeName == wxT("property") )
{
// property
wxString clas = node->GetAttribute("class");
wxString label;
wxString sLabel(wxT("label"));
if ( HasParam(sLabel) )
label = GetText(sLabel);
wxString name;
wxString sName(wxT("name"));
if ( HasParam(sName) )
name = GetText(sName);
else
name = label;
wxString sValue(wxT("value"));
wxString value;
wxString* pValue = nullptr;
if ( HasParam(sValue) )
{
value = GetText(sValue);
pValue = &value;
}
wxXmlNode* choicesNode = GetParamNode(wxT("choices"));
wxPGChoices choices;
if ( choicesNode )
{
choices = m_populator->ParseChoices( choicesNode->GetNodeContent(),
choicesNode->GetAttribute("id"));
}
wxPGProperty* property = m_populator->Add( clas, label, name, pValue, &choices );
if ( !property )
return nullptr;
wxString sFlags(wxT("flags"));
wxString flags;
if ( HasParam(sFlags) )
property->SetFlagsFromString( GetText(sFlags) );
wxString sTip(wxT("tip"));
if ( HasParam(sTip) )
property->SetHelpString(GetText(sTip));
if ( property->GetChildCount() )
{
wxString sExpanded(wxT("expanded"));
if ( HasParam(sExpanded) )
property->SetExpanded(GetBool(sExpanded));
}
// Need to call AddChildren even for non-parent properties for attributes and such
m_populator->AddChildren(property);
}
else if ( nodeName == wxT("attribute") )
{
// attribute
wxString s1 = node->GetAttribute("name");
if ( s1.length() )
{
wxPGPropertyValuesFlags flags = node->GetAttribute("recurse") == "1"
? wxPGPropertyValuesFlags::Recurse
: wxPGPropertyValuesFlags::DontRecurse;
m_populator->AddAttribute( s1, node->GetAttribute("type"),
node->GetNodeContent(), flags );
}
}
else if( m_class == wxT("wxPropertyGrid"))
{
XRC_MAKE_INSTANCE(control, wxPropertyGrid)
control->Create(m_parentAsWindow,
GetID(),
GetPosition(), GetSize(),
GetStyle(),
GetName());
m_pg = control;
HandlePropertyGridParams();
InitPopulator();
PopulatePage(control->GetState());
DonePopulator();
SetupWindow(control);
return control;
}
else if ( nodeName == wxT("choices") )
{
// choices
//
// Add choices list outside of a property
m_populator->ParseChoices( node->GetNodeContent(),
node->GetAttribute("id"));
}
else if ( nodeName == wxT("splitterpos") )
{
// splitterpos
wxASSERT(m_populator);
wxString sIndex = node->GetAttribute("index");
long index;
if ( !sIndex.ToLong(&index, 10) )
index = 0;
wxString s = node->GetNodeContent();
long pos;
if ( wxPropertyGridPopulator::ToLongPCT(s, &pos, m_pg->GetClientSize().x) )
m_populator->GetState()->DoSetSplitter( pos, index );
}
else if ( nodeName == wxT("page") )
{
// page
wxASSERT(m_manager);
wxString label;
wxString sLabel(wxT("label"));
if ( HasParam(sLabel) )
label = GetText(sLabel);
else
label = wxString::Format(_("Page %i"),(int)(m_manager->GetPageCount()+1));
m_manager->AddPage(label);
wxPropertyGridPageState* state = m_manager->GetPage(m_manager->GetPageCount()-1);
PopulatePage(state);
}
else if( m_class == wxT("wxPropertyGridManager"))
{
XRC_MAKE_INSTANCE(control, wxPropertyGridManager)
control->Create(m_parentAsWindow,
GetID(),
GetPosition(), GetSize(),
GetStyle(),
GetName());
wxPropertyGridManager* oldManager = m_manager;
m_manager = control;
m_pg = control->GetGrid();
HandlePropertyGridParams();
InitPopulator();
CreateChildrenPrivately(control, nullptr);
DonePopulator();
m_manager = oldManager;
SetupWindow(control);
return control;
}
else
{
wxFAIL_MSG( "unreachable" );
}
return nullptr;
}
bool wxPropertyGridXmlHandler::CanHandle(wxXmlNode *node)
{
wxString name = node->GetName();
return (
(
m_populator && ( name == wxT("property") ||
name == wxT("attribute") ||
name == wxT("choices") ||
name == wxT("splitterpos")
)
) ||
(m_manager && name == wxT("page")) ||
(!m_populator && IsOfClass(node, wxT("wxPropertyGrid"))) ||
(!m_populator && IsOfClass(node, wxT("wxPropertyGridManager")))
);
}
#endif // wxUSE_XRC && wxUSE_PROPGRID