Added wxPropertyGrid::SetSortFunction(); moved Sort() and SortChildren() to wxPropertyGridInterface; default sorting is now case-insensitive

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@57894 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Jaakko Salli
2009-01-07 18:53:09 +00:00
parent 5f8704a6e3
commit 433969811e
10 changed files with 286 additions and 63 deletions

View File

@@ -1008,6 +1008,45 @@ public:
m_iFlags |= wxPG_FL_SPLITTER_PRE_SET; m_iFlags |= wxPG_FL_SPLITTER_PRE_SET;
} }
/**
Sets the property sorting function.
@param sortFunction
The sorting function to be used. It should return a value greater
than 0 if position of p1 is after p2. So, for instance, when
comparing property names, you can use following implementation:
@code
int MyPropertySortFunction(wxPropertyGrid* propGrid,
wxPGProperty* p1,
wxPGProperty* p2)
{
return p1->GetBaseName().compare( p2->GetBaseName() );
}
@endcode
@remarks
Default property sort function sorts properties by their labels
(case-insensitively).
@see GetSortFunction, wxPropertyGridInterface::Sort,
wxPropertyGridInterface::SortChildren
*/
void SetSortFunction( wxPGSortCallback sortFunction )
{
m_sortFunction = sortFunction;
}
/**
Returns the property sort function (default is @NULL).
@see SetSortFunction
*/
wxPGSortCallback GetSortFunction() const
{
return m_sortFunction;
}
/** Set virtual width for this particular page. Width -1 indicates that the /** Set virtual width for this particular page. Width -1 indicates that the
virtual width should be disabled. */ virtual width should be disabled. */
void SetVirtualWidth( int width ); void SetVirtualWidth( int width );
@@ -1041,13 +1080,6 @@ public:
DoShowPropertyError(p, msg); DoShowPropertyError(p, msg);
} }
/** Sorts all items at all levels (except sub-properties). */
void Sort();
/** Sorts children of a category.
*/
void SortChildren( wxPGPropArg id );
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
// //
// Following methods do not need to be (currently) documented // Following methods do not need to be (currently) documented
@@ -1577,6 +1609,9 @@ protected:
// Top level parent // Top level parent
wxWindow* m_tlp; wxWindow* m_tlp;
// Sort function
wxPGSortCallback m_sortFunction;
// y coordinate of property that mouse hovering // y coordinate of property that mouse hovering
int m_propHoverY; int m_propHoverY;
// Which column's editor is selected (usually 1)? // Which column's editor is selected (usually 1)?

View File

@@ -301,6 +301,29 @@ class wxPGValidationInfo;
#define wxPG_DEFAULT_IMAGE_SIZE wxSize(-1, -1) #define wxPG_DEFAULT_IMAGE_SIZE wxSize(-1, -1)
/** This callback function is used for sorting properties.
Call wxPropertyGrid::SetSortFunction() to set it.
Sort function should return a value greater than 0 if position of p1 is
after p2. So, for instance, when comparing property names, you can use
following implementation:
@code
int MyPropertySortFunction(wxPropertyGrid* propGrid,
wxPGProperty* p1,
wxPGProperty* p2)
{
return p1->GetBaseName().compare( p2->GetBaseName() );
}
@endcode
*/
typedef int (*wxPGSortCallback)(wxPropertyGrid* propGrid,
wxPGProperty* p1,
wxPGProperty* p2);
typedef wxString wxPGCachedString; typedef wxString wxPGCachedString;
/** @} /** @}

View File

@@ -1226,6 +1226,30 @@ public:
*/ */
void SetValidationFailureBehavior( int vfbFlags ); void SetValidationFailureBehavior( int vfbFlags );
/**
Sorts all properties.
@see SortChildren, wxPropertyGrid::SetSortFunction
*/
void Sort();
/**
Sorts children of a property.
@param id
Name or pointer to a property.
@param recursively
If @true, then children are sorted recursively.
@see Sort, wxPropertyGrid::SetSortFunction
*/
void SortChildren( wxPGPropArg id, bool recursively = false )
{
wxPG_PROP_ARG_CALL_PROLOG()
m_pState->DoSortChildren(p, recursively);
}
#ifdef SWIG #ifdef SWIG
%pythoncode { %pythoncode {
def MapType(class_,factory): def MapType(class_,factory):

View File

@@ -613,8 +613,8 @@ public:
/** Set virtual width for this particular page. */ /** Set virtual width for this particular page. */
void SetVirtualWidth( int width ); void SetVirtualWidth( int width );
void SortChildren( wxPGProperty* p ); void DoSortChildren( wxPGProperty* p, bool recursively = false );
void Sort(); void DoSort();
void SetSelection( wxPGProperty* p ) { m_selected = p; } void SetSelection( wxPGProperty* p ) { m_selected = p; }

View File

@@ -271,6 +271,27 @@ enum wxPG_KEYBOARD_ACTIONS
/** @} /** @}
*/ */
/** This callback function is used for sorting properties.
Call wxPropertyGrid::SetSortFunction() to set it.
Sort function should return a value greater than 0 if position of p1 is
after p2. So, for instance, when comparing property names, you can use
following implementation:
@code
int MyPropertySortFunction(wxPropertyGrid* propGrid,
wxPGProperty* p1,
wxPGProperty* p2)
{
return p1->GetBaseName().compare( p2->GetBaseName() );
}
@endcode
*/
typedef int (*wxPGSortCallback)(wxPropertyGrid* propGrid,
wxPGProperty* p1,
wxPGProperty* p2);
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
/** /**
@@ -621,6 +642,13 @@ public:
*/ */
wxColour GetSelectionForegroundColour() const; wxColour GetSelectionForegroundColour() const;
/**
Returns the property sort function (default is @NULL).
@see SetSortFunction
*/
wxPGSortCallback GetSortFunction() const;
/** /**
Returns current splitter x position. Returns current splitter x position.
*/ */
@@ -772,6 +800,33 @@ public:
*/ */
void SetSelectionTextColour(const wxColour& col); void SetSelectionTextColour(const wxColour& col);
/**
Sets the property sorting function.
@param sortFunction
The sorting function to be used. It should return a value greater
than 0 if position of p1 is after p2. So, for instance, when
comparing property names, you can use following implementation:
@code
int MyPropertySortFunction(wxPropertyGrid* propGrid,
wxPGProperty* p1,
wxPGProperty* p2)
{
return p1->GetBaseName().compare( p2->GetBaseName() );
}
@endcode
@remarks
Default property sort function sorts properties by their labels
(case-insensitively).
@see GetSortFunction, wxPropertyGridInterface::Sort,
wxPropertyGridInterface::SortChildren
*/
void SetSortFunction( wxPGSortCallback sortFunction );
/** /**
Sets x coordinate of the splitter. Sets x coordinate of the splitter.
@@ -801,24 +856,6 @@ public:
Shows an brief error message that is related to a property. Shows an brief error message that is related to a property.
*/ */
void ShowPropertyError( wxPGPropArg id, const wxString& msg ); void ShowPropertyError( wxPGPropArg id, const wxString& msg );
/**
Sorts all items at all levels (except private children).
@remarks This functions deselects selected property, if any. Validation
failure option wxPG_VFB_STAY_IN_PROPERTY is not respected, ie.
selection is cleared even if editor had invalid value.
*/
void Sort();
/**
Sorts children of a property.
@remarks This functions deselects selected property, if any. Validation
failure option wxPG_VFB_STAY_IN_PROPERTY is not respected, ie.
selection is cleared even if editor had invalid value.
*/
void SortChildren( wxPGPropArg id );
}; };

View File

@@ -901,6 +901,26 @@ public:
*/ */
void SetValidationFailureBehavior( int vfbFlags ); void SetValidationFailureBehavior( int vfbFlags );
/**
Sorts all properties.
@see SortChildren, wxPropertyGrid::SetSortFunction
*/
void Sort();
/**
Sorts children of a property.
@param id
Name or pointer to a property.
@param recursively
If @true, then children are sorted recursively.
@see Sort, wxPropertyGrid::SetSortFunction
*/
void SortChildren( wxPGPropArg id, bool recursively = false );
/** /**
Returns editor pointer of editor with given name; Returns editor pointer of editor with given name;
*/ */

View File

@@ -306,6 +306,15 @@ wxArrayPGProperty GetPropertiesInRandomOrder( wxPropertyGridInterface* props, in
return arr; return arr;
} }
// Callback for testing property sorting
int MyPropertySortFunction(wxPropertyGrid* WXUNUSED(propGrid),
wxPGProperty* p1,
wxPGProperty* p2)
{
// Reverse alphabetical order
return p2->GetLabel().CmpNoCase( p1->GetBaseName() );
}
bool FormMain::RunTests( bool fullTest, bool interactive ) bool FormMain::RunTests( bool fullTest, bool interactive )
{ {
wxString t; wxString t;
@@ -935,6 +944,51 @@ bool FormMain::RunTests( bool fullTest, bool interactive )
pgman->Update(); pgman->Update();
} }
{
RT_START_TEST(SortFunction)
wxPGProperty* p;
// Make sure indexes are as supposed
p = pgman->GetProperty(wxT("User Name"));
if ( p->GetIndexInParent() != 3 )
RT_FAILURE();
p = pgman->GetProperty(wxT("User Id"));
if ( p->GetIndexInParent() != 2 )
RT_FAILURE();
p = pgman->GetProperty(wxT("User Home"));
if ( p->GetIndexInParent() != 1 )
RT_FAILURE();
p = pgman->GetProperty(wxT("Operating System"));
if ( p->GetIndexInParent() != 0 )
RT_FAILURE();
pgman->GetGrid()->SetSortFunction(MyPropertySortFunction);
pgman->GetGrid()->SortChildren(wxT("Environment"));
// Make sure indexes have been reversed
p = pgman->GetProperty(wxT("User Name"));
if ( p->GetIndexInParent() != 0 )
RT_FAILURE();
p = pgman->GetProperty(wxT("User Id"));
if ( p->GetIndexInParent() != 1 )
RT_FAILURE();
p = pgman->GetProperty(wxT("User Home"));
if ( p->GetIndexInParent() != 2 )
RT_FAILURE();
p = pgman->GetProperty(wxT("Operating System"));
if ( p->GetIndexInParent() != 3 )
RT_FAILURE();
}
{ {
RT_START_TEST(SetPropertyBackgroundColour) RT_START_TEST(SetPropertyBackgroundColour)
wxCommandEvent evt; wxCommandEvent evt;

View File

@@ -462,6 +462,7 @@ void wxPropertyGrid::Init1()
m_eventObject = this; m_eventObject = this;
m_curFocused = (wxWindow*) NULL; m_curFocused = (wxWindow*) NULL;
m_tlwHandler = NULL; m_tlwHandler = NULL;
m_sortFunction = NULL;
m_inDoPropertyChanged = 0; m_inDoPropertyChanged = 0;
m_inCommitChangesFromEditor = 0; m_inCommitChangesFromEditor = 0;
m_inDoSelectProperty = 0; m_inDoSelectProperty = 0;
@@ -2292,24 +2293,6 @@ void wxPropertyGrid::SwitchState( wxPropertyGridPageState* pNewState )
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
void wxPropertyGrid::SortChildren( wxPGPropArg id )
{
wxPG_PROP_ARG_CALL_PROLOG()
m_pState->SortChildren( p );
}
// -----------------------------------------------------------------------
void wxPropertyGrid::Sort()
{
ClearSelection(false); // This must be before state clear
m_pState->Sort();
}
// -----------------------------------------------------------------------
// Call to SetSplitterPosition will always disable splitter auto-centering // Call to SetSplitterPosition will always disable splitter auto-centering
// if parent window is shown. // if parent window is shown.
void wxPropertyGrid::DoSetSplitterPosition_( int newxpos, bool refresh, int splitterIndex, bool allPages ) void wxPropertyGrid::DoSetSplitterPosition_( int newxpos, bool refresh, int splitterIndex, bool allPages )

View File

@@ -762,6 +762,25 @@ bool wxPropertyGridInterface::Expand( wxPGPropArg id )
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
void wxPropertyGridInterface::Sort()
{
wxPropertyGrid* pg = GetPropertyGrid();
pg->ClearSelection(false);
unsigned int pageIndex = 0;
for (;;)
{
wxPropertyGridPageState* page = GetPageState(pageIndex);
if ( !page ) break;
page->DoSort();
pageIndex++;
}
}
// -----------------------------------------------------------------------
void wxPropertyGridInterface::SetPropertyLabel( wxPGPropArg id, const wxString& newproplabel ) void wxPropertyGridInterface::SetPropertyLabel( wxPGPropArg id, const wxString& newproplabel )
{ {
wxPG_PROP_ARG_CALL_PROLOG() wxPG_PROP_ARG_CALL_PROLOG()

View File

@@ -602,54 +602,82 @@ bool wxPropertyGridPageState::EnableCategories( bool enable )
#if wxUSE_STL #if wxUSE_STL
#include <algorithm> #include <algorithm>
static bool wxPG_SortFunc(wxPGProperty *p1, wxPGProperty *p2) static bool wxPG_SortFunc_ByFunction(wxPGProperty *p1, wxPGProperty *p2)
{ {
return p1->GetLabel() < p2->GetLabel(); wxPropertyGrid* pg = p1->GetGrid();
wxPGSortCallback sortFunction = pg->GetSortFunction();
return sortFunction(pg, p1, p2) < 0;
}
static bool wxPG_SortFunc_ByLabel(wxPGProperty *p1, wxPGProperty *p2)
{
return p1->GetLabel().CmpNoCase( p2->GetLabel() ) < 0;
} }
#else #else
static int wxPG_SortFunc(wxPGProperty **p1, wxPGProperty **p2) static int wxPG_SortFunc_ByFunction(wxPGProperty **pp1, wxPGProperty **pp2)
{ {
wxPGProperty *pp1 = *p1; wxPGProperty *p1 = *pp1;
wxPGProperty *pp2 = *p2; wxPGProperty *p2 = *pp2;
return pp1->GetLabel().compare( pp2->GetLabel() ); wxPropertyGrid* pg = p1->GetGrid();
wxPGSortCallback sortFunction = pg->GetSortFunction();
return sortFunction(pg, p1, p2);
}
static int wxPG_SortFunc_ByLabel(wxPGProperty **pp1, wxPGProperty **pp2)
{
wxPGProperty *p1 = *pp1;
wxPGProperty *p2 = *pp2;
return p1->GetLabel().CmpNoCase( p2->GetLabel() );
} }
#endif #endif
void wxPropertyGridPageState::SortChildren( wxPGProperty* p ) void wxPropertyGridPageState::DoSortChildren( wxPGProperty* p,
bool recursively )
{ {
if ( !p ) if ( !p )
p = (wxPGProperty*)m_properties; p = m_properties;
if ( !p->GetChildCount() ) if ( !p->GetChildCount() )
return; return;
wxPGProperty* pwc = (wxPGProperty*)p;
// Can only sort items with children // Can only sort items with children
if ( pwc->GetChildCount() < 1 ) if ( p->GetChildCount() < 1 )
return; return;
#if wxUSE_STL #if wxUSE_STL
std::sort(pwc->m_children.begin(), pwc->m_children.end(), wxPG_SortFunc); if ( GetGrid()->GetSortFunction() )
std::sort(p->m_children.begin(), p->m_children.end(),
wxPG_SortFunc_ByFunction);
else
std::sort(p->m_children.begin(), p->m_children.end(),
wxPG_SortFunc_ByLabel);
#else #else
pwc->m_children.Sort( wxPG_SortFunc ); if ( GetGrid()->GetSortFunction() )
p->m_children.Sort( wxPG_SortFunc_ByFunction );
else
p->m_children.Sort( wxPG_SortFunc_ByLabel );
#endif #endif
// Fix indexes // Fix indexes
pwc->FixIndicesOfChildren(); p->FixIndicesOfChildren();
if ( recursively && !p->HasFlag(wxPG_PROP_AGGREGATE) )
{
for ( unsigned int i=0; i<p->GetChildCount(); i++ )
DoSortChildren(p->Item(i));
}
} }
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
void wxPropertyGridPageState::Sort() void wxPropertyGridPageState::DoSort()
{ {
SortChildren( m_properties ); DoSortChildren( m_properties, true );
// Sort categories as well // Sort categories as well (but we need not do it recursively)
if ( !IsInNonCatMode() ) if ( !IsInNonCatMode() )
{ {
size_t i; size_t i;
@@ -657,7 +685,7 @@ void wxPropertyGridPageState::Sort()
{ {
wxPGProperty* p = m_properties->Item(i); wxPGProperty* p = m_properties->Item(i);
if ( p->IsCategory() ) if ( p->IsCategory() )
SortChildren( p ); DoSortChildren( p );
} }
} }
} }