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.
297 lines
8.2 KiB
C++
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
|