wxPGProperty::AddChild() can now be used to add normal child properties (previously it was only used to add private children of derived property classes such as wxFontProperty and wxFlagsProperty). However, to allow backwards compatibility, SetParentalStyle(wxPG_PROP_MISC_PARENT) needs to be called before doing so. Also done: merged property initialization code from PrepareToAddItem() and PrepareSubProperties() to InitAfterAdded().

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@56309 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Jaakko Salli 2008-10-14 17:15:59 +00:00
parent c8c86bd0ba
commit 2fd4a52415
11 changed files with 261 additions and 201 deletions

View File

@ -974,7 +974,11 @@ public:
variant << value;
SetValue(variant);
// If has private child properties then create them here, e.g.:
// If has private child properties then create them here. Also
// set flag that indicates presence of private children. E.g.:
//
// SetParentalType(wxPG_PROP_AGGREGATE);
//
// AddChild( new wxStringProperty( "Subprop 1",
// wxPG_LABEL,
// value.GetSubProp1() ) );
@ -1795,6 +1799,27 @@ public:
inline void SetName( const wxString& newName );
/**
Changes what sort of parent this property is for its children.
@param flag
Use one of the following values: wxPG_PROP_MISC_PARENT (for generic
parents), wxPG_PROP_CATEGORY (for categories), or
wxPG_PROP_AGGREGATE (for derived property classes with private
children).
@remarks You only need to call this if you use AddChild() to add
child properties. Adding properties with
wxPropertyGridInterface::Insert() or
wxPropertyGridInterface::AppendIn() will automatically set
property to use wxPG_PROP_MISC_PARENT style.
*/
void SetParentalType( int flag )
{
m_flags &= ~(wxPG_PROP_PROPERTY|wxPG_PROP_PARENTAL_FLAGS);
m_flags |= flag;
}
void SetValueToUnspecified()
{
wxVariant val; // Create NULL variant
@ -1883,7 +1908,23 @@ public:
*/
void AdaptListToValue( wxVariant& list, wxVariant* value ) const;
/** This is used by properties that have fixed sub-properties. */
/**
Adds a child property. If you use this instead of
wxPropertyGridInterface::Insert() or
wxPropertyGridInterface::AppendIn(), then you must set up
property's parental type before making the call. To do this,
call property's SetParentalType() function with either
wxPG_PROP_MISC_PARENT (normal, public children) or with
wxPG_PROP_AGGREGATE (private children for subclassed property).
For instance:
@code
wxPGProperty* prop = new wxStringProperty(wxS("Property"));
prop->SetParentalType(wxPG_PROP_MISC_PARENT);
wxPGProperty* prop2 = new wxStringProperty(wxS("Property2"));
prop->AddChild(prop2);
@endcode
*/
void AddChild( wxPGProperty* prop );
/** Returns height of children, recursively, and
@ -1990,18 +2031,12 @@ protected:
void DoSetName(const wxString& str) { m_name = str; }
// Call for after sub-properties added with AddChild
void PrepareSubProperties();
void InitAfterAdded( wxPropertyGridPageState* pageState,
wxPropertyGrid* propgrid );
// Removes child property with given pointer. Does not delete it.
void RemoveChild( wxPGProperty* p );
void SetParentalType( int flag )
{
m_flags &= ~(wxPG_PROP_PROPERTY|wxPG_PROP_PARENTAL_FLAGS);
m_flags |= flag;
}
void SetParentState( wxPropertyGridPageState* pstate )
{ m_parentState = pstate; }

View File

@ -1223,6 +1223,8 @@ public:
void OnCustomEditorEvent( wxCommandEvent &event );
long GetInternalFlags() const { return m_iFlags; }
bool HasInternalFlag( long flag ) const
{ return (m_iFlags & flag) ? true : false; }
void SetInternalFlag( long flag ) { m_iFlags |= flag; }
void ClearInternalFlag( long flag ) { m_iFlags &= ~(flag); }
void IncFrozen() { m_frozen++; }

View File

@ -636,7 +636,7 @@ protected:
*/
int HitTestH( int x, int* pSplitterHit, int* pSplitterHitOffset ) const;
int PrepareToAddItem ( wxPGProperty* property,
bool PrepareToAddItem( wxPGProperty* property,
wxPGProperty* scheduledParent );
/** If visible, then this is pointer to wxPropertyGrid.

View File

@ -868,8 +868,21 @@ public:
int AddChoice( const wxString& label, int value = wxPG_INVALID_VALUE );
/**
Properties which have private child properties should add them
with this function, called in their constructor.
Adds a child property. If you use this instead of
wxPropertyGridInterface::Insert() or
wxPropertyGridInterface::AppendIn(), then you must set up
property's parental type before making the call. To do this,
call property's SetParentalType() function with either
wxPG_PROP_MISC_PARENT (normal, public children) or with
wxPG_PROP_AGGREGATE (private children for subclassed property).
For instance:
@code
wxPGProperty* prop = new wxStringProperty(wxS("Property"));
prop->SetParentalType(wxPG_PROP_MISC_PARENT);
wxPGProperty* prop2 = new wxStringProperty(wxS("Property2"));
prop->AddChild(prop2);
@endcode
*/
void AddChild( wxPGProperty* property );
@ -1299,6 +1312,23 @@ public:
*/
void SetName( const wxString& newName );
/**
Changes what sort of parent this property is for its children.
@param flag
Use one of the following values: wxPG_PROP_MISC_PARENT (for generic
parents), wxPG_PROP_CATEGORY (for categories), or
wxPG_PROP_AGGREGATE (for derived property classes with private
children).
@remarks You only need to call this if you use AddChild() to add
child properties. Adding properties with
wxPropertyGridInterface::Insert() or
wxPropertyGridInterface::AppendIn() will automatically set
property to use wxPG_PROP_MISC_PARENT style.
*/
void SetParentalType( int flag );
/** Sets wxValidator for a property */
void SetValidator( const wxValidator& validator );

View File

@ -476,6 +476,7 @@ wxVectorProperty::wxVectorProperty( const wxString& label,
: wxPGProperty(label,name)
{
SetValue( WXVARIANT(value) );
SetParentalType(wxPG_PROP_AGGREGATE);
AddChild( new wxFloatProperty(wxT("X"),wxPG_LABEL,value.x) );
AddChild( new wxFloatProperty(wxT("Y"),wxPG_LABEL,value.y) );
AddChild( new wxFloatProperty(wxT("Z"),wxPG_LABEL,value.z) );
@ -524,6 +525,7 @@ wxTriangleProperty::wxTriangleProperty( const wxString& label,
: wxPGProperty(label,name)
{
SetValue( WXVARIANT(value) );
SetParentalType(wxPG_PROP_AGGREGATE);
AddChild( new wxVectorProperty(wxT("A"),wxPG_LABEL,value.a) );
AddChild( new wxVectorProperty(wxT("B"),wxPG_LABEL,value.b) );
AddChild( new wxVectorProperty(wxT("C"),wxPG_LABEL,value.c) );
@ -1683,11 +1685,21 @@ void FormMain::PopulateWithExamples ()
//
// Test how non-editable composite strings appear
pid = pg->Append( new wxStringProperty(wxT("wxWidgets Traits"), wxPG_LABEL, wxT("<composed>")) );
pid = new wxStringProperty(wxT("wxWidgets Traits"), wxPG_LABEL, wxT("<composed>"));
pg->SetPropertyReadOnly(pid);
pg->AppendIn(pid, new wxStringProperty(wxT("Latest Release"), wxPG_LABEL, wxT("2.8.8")) );
pg->AppendIn(pid, new wxBoolProperty(wxT("Win API"), wxPG_LABEL, true) );
//
// For testing purposes, combine two methods of adding children
//
// AddChild() requires that we call this
pid->SetParentalType(wxPG_PROP_MISC_PARENT);
pid->AddChild( new wxStringProperty(wxT("Latest Release"), wxPG_LABEL, wxT("2.8.8")));
pid->AddChild( new wxBoolProperty(wxT("Win API"), wxPG_LABEL, true) );
pg->Append( pid );
pg->AppendIn(pid, new wxBoolProperty(wxT("QT"), wxPG_LABEL, false) );
pg->AppendIn(pid, new wxBoolProperty(wxT("Cocoa"), wxPG_LABEL, true) );
pg->AppendIn(pid, new wxBoolProperty(wxT("BeOS"), wxPG_LABEL, false) );

View File

@ -67,6 +67,8 @@ wxFontDataProperty::wxFontDataProperty( const wxString& label, const wxString& n
// (instead of calling SetValue) in derived (wxObject) properties.
m_value_wxFontData << value;
SetParentalType(wxPG_PROP_AGGREGATE);
// Add extra children.
AddChild( new wxColourProperty(_("Colour"), wxPG_LABEL,
fontData.GetColour() ) );
@ -197,6 +199,7 @@ wxSizeProperty::wxSizeProperty( const wxString& label, const wxString& name,
const wxSize& value) : wxPGProperty(label,name)
{
SetValueI(value);
SetParentalType(wxPG_PROP_AGGREGATE);
AddChild( new wxIntProperty(wxT("Width"),wxPG_LABEL,value.x) );
AddChild( new wxIntProperty(wxT("Height"),wxPG_LABEL,value.y) );
}
@ -233,6 +236,7 @@ wxPointProperty::wxPointProperty( const wxString& label, const wxString& name,
const wxPoint& value) : wxPGProperty(label,name)
{
SetValueI(value);
SetParentalType(wxPG_PROP_AGGREGATE);
AddChild( new wxIntProperty(wxT("X"),wxPG_LABEL,value.x) );
AddChild( new wxIntProperty(wxT("Y"),wxPG_LABEL,value.y) );
}

View File

@ -477,6 +477,8 @@ wxFontProperty::wxFontProperty( const wxString& label, const wxString& name,
wxFont font;
font << m_value;
SetParentalType(wxPG_PROP_AGGREGATE);
AddChild( new wxIntProperty( _("Point Size"), wxS("Point Size"),(long)font.GetPointSize() ) );
AddChild( new wxEnumProperty(_("Family"), wxS("PointSize"),

View File

@ -411,6 +411,132 @@ void wxPGProperty::Init( const wxString& label, const wxString& name )
Init();
}
void wxPGProperty::InitAfterAdded( wxPropertyGridPageState* pageState,
wxPropertyGrid* propgrid )
{
//
// Called after property has been added to grid or page
// (so propgrid can be NULL, too).
wxPGProperty* parent = m_parent;
bool parentIsRoot = parent->IsKindOf(CLASSINFO(wxPGRootProperty));
m_parentState = pageState;
if ( !parentIsRoot )
{
m_bgColIndex = parent->m_bgColIndex;
m_fgColIndex = parent->m_fgColIndex;
}
// If in hideable adding mode, or if assigned parent is hideable, then
// make this one hideable.
if (
( !parentIsRoot && parent->HasFlag(wxPG_PROP_HIDDEN) ) ||
( propgrid && (propgrid->HasInternalFlag(wxPG_FL_ADDING_HIDEABLES)) )
)
SetFlag( wxPG_PROP_HIDDEN );
// Set custom image flag.
int custImgHeight = OnMeasureImage().y;
if ( custImgHeight < 0 )
{
SetFlag(wxPG_PROP_CUSTOMIMAGE);
}
if ( propgrid && (propgrid->HasFlag(wxPG_LIMITED_EDITING)) )
SetFlag(wxPG_PROP_NOEDITOR);
// Make sure parent has some parental flags
if ( !parent->HasFlag(wxPG_PROP_PARENTAL_FLAGS) )
parent->SetParentalType(wxPG_PROP_MISC_PARENT);
if ( !IsCategory() )
{
// This is not a category.
// Depth.
//
unsigned char depth = 1;
if ( !parentIsRoot )
{
depth = parent->m_depth;
if ( !parent->IsCategory() )
depth++;
}
m_depth = depth;
unsigned char greyDepth = depth;
if ( !parentIsRoot )
{
wxPropertyCategory* pc;
if ( parent->IsCategory() )
pc = (wxPropertyCategory* ) parent;
else
// This conditional compile is necessary to
// bypass some compiler bug.
pc = pageState->GetPropertyCategory(parent);
if ( pc )
greyDepth = pc->GetDepth();
else
greyDepth = parent->m_depthBgCol;
}
m_depthBgCol = greyDepth;
}
else
{
// This is a category.
// depth
unsigned char depth = 1;
if ( !parentIsRoot )
{
depth = parent->m_depth + 1;
}
m_depth = depth;
m_depthBgCol = depth;
}
//
// Has initial children
if ( GetChildCount() )
{
FlagType parentalFlags = m_flags & wxPG_PROP_PARENTAL_FLAGS;
// Check parental flags
wxASSERT_MSG( parentalFlags,
"Call SetFlag(wxPG_PROP_MISC_PARENT) or"
"SetFlag(wxPG_PROP_AGGREGATE) before calling"
"wxPGProperty::AddChild()." );
if ( HasFlag(wxPG_PROP_AGGREGATE) )
{
// Properties with private children are not expanded by default.
SetExpanded(false);
}
else if ( propgrid && propgrid->HasFlag(wxPG_HIDE_MARGIN) )
{
// ...unless it cannot be expanded by user and therefore must
// remain visible at all times
SetExpanded(true);
}
//
// Prepare children recursively
for ( unsigned int i=0; i<GetChildCount(); i++ )
{
wxPGProperty* child = Item(i);
child->InitAfterAdded(pageState, pageState->GetGrid());
}
if ( propgrid && (propgrid->GetExtraStyle() & wxPG_EX_AUTO_UNSPECIFIED_VALUES) )
SetFlagRecursively(wxPG_PROP_AUTO_UNSPECIFIED, true);
}
}
wxPGProperty::wxPGProperty()
: wxObject()
{
@ -1915,74 +2041,6 @@ bool wxPGProperty::IsTextEditable() const
return true;
}
// Call for after sub-properties added with AddChild
void wxPGProperty::PrepareSubProperties()
{
wxPropertyGridPageState* state = GetParentState();
wxASSERT(state);
if ( !GetChildCount() )
return;
wxByte depth = m_depth + 1;
wxByte depthBgCol = m_depthBgCol;
FlagType inheritFlags = m_flags & wxPG_INHERITED_PROPFLAGS;
wxByte bgColIndex = m_bgColIndex;
wxByte fgColIndex = m_fgColIndex;
//
// Set some values to the children
//
size_t i = 0;
wxPGProperty* nparent = this;
while ( i < nparent->GetChildCount() )
{
wxPGProperty* np = nparent->Item(i);
np->m_parentState = state;
np->m_flags |= inheritFlags; // Hideable also if parent.
np->m_depth = depth;
np->m_depthBgCol = depthBgCol;
np->m_bgColIndex = bgColIndex;
np->m_fgColIndex = fgColIndex;
// Also handle children of children
if ( np->GetChildCount() > 0 )
{
nparent = np;
i = 0;
// Init
nparent->SetParentalType(wxPG_PROP_AGGREGATE);
nparent->SetExpanded(false);
depth++;
}
else
{
// Next sibling
i++;
}
// After reaching last sibling, go back to processing
// siblings of the parent
while ( i >= nparent->GetChildCount() )
{
// Exit the loop when top parent hit
if ( nparent == this )
break;
depth--;
i = nparent->GetIndexInParent() + 1;
nparent = nparent->GetParent();
}
}
}
// Call after fixed sub-properties added/removed after creation.
// if oldSelInd >= 0 and < new max items, then selection is
// moved to it. Note: oldSelInd -2 indicates that this property
@ -1992,7 +2050,13 @@ void wxPGProperty::SubPropsChanged( int oldSelInd )
wxPropertyGridPageState* state = GetParentState();
wxPropertyGrid* grid = state->GetGrid();
PrepareSubProperties();
//
// Re-repare children (recursively)
for ( unsigned int i=0; i<GetChildCount(); i++ )
{
wxPGProperty* child = Item(i);
child->InitAfterAdded(state, grid);
}
wxPGProperty* sel = (wxPGProperty*) NULL;
if ( oldSelInd >= (int)m_children.size() )

View File

@ -1476,7 +1476,8 @@ void wxPropertyGrid::DoSetPropertyValueUnspecified( wxPGProperty* p )
DrawItemAndChildren(p);
wxPGProperty* parent = p->GetParent();
while ( (parent->GetFlags() & wxPG_PROP_PARENTAL_FLAGS) == wxPG_PROP_MISC_PARENT )
while ( parent &&
(parent->GetFlags() & wxPG_PROP_PARENTAL_FLAGS) == wxPG_PROP_MISC_PARENT )
{
DrawItem(parent);
parent = parent->GetParent();

View File

@ -1508,8 +1508,8 @@ void wxPropertyGridPageState::DoSetPropertyValues( const wxVariantList& list, wx
// wxPropertyGridPageState property adding and removal
// -----------------------------------------------------------------------
int wxPropertyGridPageState::PrepareToAddItem( wxPGProperty* property,
wxPGProperty* scheduledParent )
bool wxPropertyGridPageState::PrepareToAddItem( wxPGProperty* property,
wxPGProperty* scheduledParent )
{
wxPropertyGrid* propGrid = m_pPropGrid;
@ -1545,7 +1545,7 @@ int wxPropertyGridPageState::PrepareToAddItem( wxPGProperty* property,
{
delete property;
m_currentCategory = pwc;
return 2; // Tells the caller what we did.
return false;
}
}
}
@ -1566,119 +1566,30 @@ int wxPropertyGridPageState::PrepareToAddItem( wxPGProperty* property,
{
bool selRes = propGrid->ClearSelection();
wxPG_CHECK_MSG_DBG( selRes,
-1,
true,
wxT("failed to deselect a property (editor probably had invalid value)") );
}
if ( scheduledParent )
// NULL parent == root parent
if ( !scheduledParent )
scheduledParent = DoGetRoot();
property->m_parent = scheduledParent;
property->InitAfterAdded(this, propGrid);
if ( property->IsCategory() )
{
// Use parent's colours.
property->m_bgColIndex = scheduledParent->m_bgColIndex;
property->m_fgColIndex = scheduledParent->m_fgColIndex;
wxPropertyCategory* pc = wxStaticCast(property, wxPropertyCategory);
// Fix no parent does not yet have parenting flag yet, set one now
if ( !scheduledParent->HasFlag(wxPG_PROP_PARENTAL_FLAGS) )
scheduledParent->SetParentalType(wxPG_PROP_MISC_PARENT);
//scheduledParent->SetFlag(wxPG_PROP_MISC_PARENT);
}
m_currentCategory = pc;
// If in hideable adding mode, or if assigned parent is hideable, then
// make this one hideable.
if (
( scheduledParent && (scheduledParent->m_flags & wxPG_PROP_HIDDEN) ) ||
( propGrid && (propGrid->m_iFlags & wxPG_FL_ADDING_HIDEABLES) )
)
property->SetFlag( wxPG_PROP_HIDDEN );
// Set custom image flag.
int custImgHeight = property->OnMeasureImage().y;
if ( custImgHeight < 0 /*|| custImgHeight > 1*/ )
{
property->m_flags |= wxPG_PROP_CUSTOMIMAGE;
}
if ( propGrid && (propGrid->GetWindowStyleFlag() & wxPG_LIMITED_EDITING) )
property->m_flags |= wxPG_PROP_NOEDITOR;
if ( !property->IsCategory() )
{
// This is not a category.
//wxASSERT_MSG( property->GetEditorClass(), wxT("Editor class not initialized!") );
// Depth.
//
unsigned char depth = 1;
if ( scheduledParent )
{
depth = scheduledParent->m_depth;
if ( !scheduledParent->IsCategory() )
depth++;
}
property->m_depth = depth;
unsigned char greyDepth = depth;
if ( scheduledParent )
{
wxPropertyCategory* pc;
if ( scheduledParent->IsCategory() || scheduledParent->IsRoot() )
pc = (wxPropertyCategory*)scheduledParent;
else
// This conditional compile is necessary to
// bypass some compiler bug.
pc = GetPropertyCategory(scheduledParent);
if ( pc )
greyDepth = pc->GetDepth();
else
greyDepth = scheduledParent->m_depthBgCol;
}
property->m_depthBgCol = greyDepth;
// Prepare children pre-added children
if ( property->GetChildCount() )
{
property->SetParentalType(wxPG_PROP_AGGREGATE);
property->SetExpanded(false); // Properties with children are not expanded by default.
if ( propGrid && propGrid->GetWindowStyleFlag() & wxPG_HIDE_MARGIN )
property->SetExpanded(true); // ...unless it cannot be expanded.
property->PrepareSubProperties();
return -1;
}
if ( propGrid && (propGrid->GetExtraStyle() & wxPG_EX_AUTO_UNSPECIFIED_VALUES) )
property->SetFlagRecursively(wxPG_PROP_AUTO_UNSPECIFIED, true);
return 0;
}
else
{
// This is a category.
// depth
unsigned char depth = 1;
if ( scheduledParent )
{
depth = scheduledParent->m_depth + 1;
}
property->m_depth = depth;
property->m_depthBgCol = depth;
m_currentCategory = (wxPropertyCategory*)property;
wxPropertyCategory* pc = (wxPropertyCategory*)property;
// Calculate text extent for caption item.
// Calculate text extent for category caption
if ( propGrid )
pc->CalculateTextExtent(propGrid, propGrid->GetCaptionFont());
return 1;
}
return true;
}
// -----------------------------------------------------------------------
@ -1703,11 +1614,11 @@ wxPGProperty* wxPropertyGridPageState::DoInsert( wxPGProperty* parent, int index
wxNullProperty,
wxT("when adding properties to fixed parents, use BeginAddChildren and EndAddChildren.") );
int parenting = PrepareToAddItem( property, (wxPropertyCategory*)parent );
bool res = PrepareToAddItem( property, (wxPropertyCategory*)parent );
// This type of invalid parenting value indicates we should exit now, returning
// id of most recent category.
if ( parenting > 1 )
// PrepareToAddItem() may just decide to use use current category
// instead of adding new one.
if ( !res )
return m_currentCategory;
// Note that item must be added into current mode later.
@ -1736,7 +1647,7 @@ wxPGProperty* wxPropertyGridPageState::DoInsert( wxPGProperty* parent, int index
// Categorized mode
// Only add non-categories to m_abcArray.
if ( m_abcArray && parenting <= 0 )
if ( m_abcArray && !property->IsCategory() )
m_abcArray->AddChild2( property, -1, false );
// Add to current mode.
@ -1755,7 +1666,7 @@ wxPGProperty* wxPropertyGridPageState::DoInsert( wxPGProperty* parent, int index
m_regularArray.AddChild2( property, -1, false );
// Add to current mode (no categories).
if ( parenting <= 0 )
if ( !property->IsCategory() )
m_abcArray->AddChild2( property, index );
}
}

View File

@ -1209,8 +1209,7 @@ WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxFlagsProperty,long,TextCtrl)
void wxFlagsProperty::Init()
{
SetFlag(wxPG_PROP_AGGREGATE); // This is must be done here to support flag props
// with inital zero children.
SetParentalType(wxPG_PROP_AGGREGATE);
long value = m_value;