wxPropertyGridPageState::wxPropertyGridPageState()
{
- m_pPropGrid = (wxPropertyGrid*) NULL;
+ m_pPropGrid = NULL;
m_regularArray.SetParentState(this);
m_properties = &m_regularArray;
- m_abcArray = (wxPGRootProperty*) NULL;
- m_currentCategory = (wxPropertyCategory*) NULL;
- m_selected = (wxPGProperty*) NULL;
+ m_abcArray = NULL;
+ m_currentCategory = NULL;
+ m_selected = NULL;
m_width = 0;
m_virtualHeight = 0;
m_lastCaptionBottomnest = 1;
{
if ( !m_abcArray )
{
- m_abcArray = new wxPGRootProperty();
+ m_abcArray = new wxPGRootProperty(wxS("<Root_NonCat>"));
m_abcArray->SetParentState(this);
m_abcArray->SetFlag(wxPG_PROP_CHILDREN_ARE_COPIES);
}
wxPGProperty* parent = p->GetParent();
if ( parent->IsCategory() || parent->IsRoot() )
{
- m_abcArray->AddChild2(p);
+ m_abcArray->DoAddChild(p);
p->m_parent = &m_regularArray;
}
}
void wxPropertyGridPageState::DoClear()
{
+ if ( m_pPropGrid && m_pPropGrid->GetState() == this )
+ {
+ m_pPropGrid->ClearSelection(false);
+ }
+ else
+ {
+ m_selected = NULL;
+ }
+
m_regularArray.Empty();
if ( m_abcArray )
m_abcArray->Empty();
m_dictName.clear();
- m_currentCategory = (wxPropertyCategory*) NULL;
+ m_currentCategory = NULL;
m_lastCaptionBottomnest = 1;
m_itemsAdded = 0;
m_virtualHeight = 0;
m_vhCalcPending = 0;
-
- m_selected = (wxPGProperty*) NULL;
}
// -----------------------------------------------------------------------
long timeSinceCreation = (::wxGetLocalTimeMillis() - GetGrid()->m_timeCreated).ToLong();
// If too long, don't set splitter
- if ( timeSinceCreation < 3000 )
+ if ( timeSinceCreation < 250 )
{
- if ( m_properties->GetChildCount() || timeSinceCreation > 750 )
+ if ( m_properties->GetChildCount() )
{
SetSplitterLeft( false );
}
wxPGProperty* wxPropertyGridPageState::GetLastItem( int flags )
{
if ( !m_properties->GetChildCount() )
- return (wxPGProperty*) NULL;
+ return NULL;
wxPG_ITERATOR_CREATE_MASKS(flags, int itemExMask, int parentExMask)
return (wxPropertyCategory*)parent;
} while ( grandparent );
- return (wxPropertyCategory*) NULL;
+ return NULL;
}
// -----------------------------------------------------------------------
it = m_dictName.find(name);
if ( it != m_dictName.end() )
return (wxPGProperty*) it->second;
- return (wxPGProperty*) NULL;
+ return NULL;
}
// -----------------------------------------------------------------------
#define ITEM_ITERATION_INIT(startparent, startindex, state) \
parent = startparent; \
i = (unsigned int)startindex; \
- if ( parent == (wxPGProperty*) NULL ) \
+ if ( parent == NULL ) \
{ \
parent = state->m_properties; \
i = 0; \
#if wxUSE_STL
#include <algorithm>
-static bool wxPG_SortFunc(wxPGProperty *p1, wxPGProperty *p2)
+static bool wxPG_SortFunc_ByFunction(wxPGProperty *p1, wxPGProperty *p2)
+{
+ 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() < p2->GetLabel();
+ return p1->GetLabel().CmpNoCase( p2->GetLabel() ) < 0;
}
#else
-static int wxPG_SortFunc(wxPGProperty **p1, wxPGProperty **p2)
+static int wxPG_SortFunc_ByFunction(wxPGProperty **pp1, wxPGProperty **pp2)
{
- wxPGProperty *pp1 = *p1;
- wxPGProperty *pp2 = *p2;
- return pp1->GetLabel().compare( pp2->GetLabel() );
+ wxPGProperty *p1 = *pp1;
+ wxPGProperty *p2 = *pp2;
+ 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
-void wxPropertyGridPageState::SortChildren( wxPGProperty* p )
+void wxPropertyGridPageState::DoSortChildren( wxPGProperty* p,
+ int flags )
{
if ( !p )
- p = (wxPGProperty*)m_properties;
+ p = m_properties;
+ // Can only sort items with children
if ( !p->GetChildCount() )
return;
- wxPGProperty* pwc = (wxPGProperty*)p;
+ // Never sort children of aggregate properties
+ if ( p->HasFlag(wxPG_PROP_AGGREGATE) )
+ return;
- // Can only sort items with children
- if ( pwc->GetChildCount() < 1 )
+ if ( (flags & wxPG_SORT_TOP_LEVEL_ONLY)
+ && !p->IsCategory() && !p->IsRoot() )
return;
#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
- 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
- // Fix indexes
- pwc->FixIndicesOfChildren();
+ // Fix indices
+ p->FixIndicesOfChildren();
+ if ( flags & wxPG_RECURSE )
+ {
+ // Apply sort recursively
+ for ( unsigned int i=0; i<p->GetChildCount(); i++ )
+ DoSortChildren(p->Item(i), flags);
+ }
}
// -----------------------------------------------------------------------
-void wxPropertyGridPageState::Sort()
+void wxPropertyGridPageState::DoSort( int flags )
{
- SortChildren( m_properties );
+ DoSortChildren( m_properties, flags | wxPG_RECURSE );
- // Sort categories as well
- if ( !IsInNonCatMode() )
- {
- size_t i;
- for ( i=0;i<m_properties->GetChildCount();i++)
- {
- wxPGProperty* p = m_properties->Item(i);
- if ( p->IsCategory() )
- SortChildren( p );
- }
- }
+ // We used to sort categories as well here also if in non-categorized
+ // mode, but doing would naturally cause child indices to become
+ // corrupted.
+}
+
+// -----------------------------------------------------------------------
+
+bool wxPropertyGridPageState::PrepareAfterItemsAdded()
+{
+ if ( !m_itemsAdded ) return false;
+
+ wxPropertyGrid* pg = GetGrid();
+
+ m_itemsAdded = 0;
+
+ if ( pg->HasFlag(wxPG_AUTO_SORT) )
+ DoSort(wxPG_SORT_TOP_LEVEL_ONLY);
+
+ return true;
}
// -----------------------------------------------------------------------
{
// Outside?
if ( y < 0 )
- return (wxPGProperty*) NULL;
+ return NULL;
unsigned int a = 0;
return m_properties->GetItemAtY(y, GetGrid()->m_lineHeight, &a);
{
wxPropertyGrid* pg = GetGrid();
wxClientDC dc(pg);
- dc.SetFont(pg->m_font);
+ dc.SetFont(pg->GetFont());
int maxW = GetColumnFitWidth(dc, m_properties, 0, subProps);
{
wxPropertyGrid* pg = GetGrid();
wxClientDC dc(pg);
- dc.SetFont(pg->m_font);
+ dc.SetFont(pg->GetFont());
int marginWidth = pg->m_marginWidth;
int accWid = marginWidth;
wxPropertyGrid* pg = GetGrid();
-#ifdef __WXDEBUG__
- const bool debug = false;
-#endif
-
unsigned int i;
unsigned int lastColumn = m_colWidths.size() - 1;
int width = m_width;
//
// Column to reduce, if needed. Take last one that exceeds minimum width.
- // Except if auto splitter centering is used, in which case use widest.
int reduceCol = -1;
- int highestColWidth = 0;
-#ifdef __WXDEBUG__
- if ( debug )
- wxLogDebug(wxT("ColumnWidthCheck (virtualWidth: %i, clientWidth: %i)"), width, clientWidth);
-#endif
+ wxLogTrace("propgrid",
+ wxS("ColumnWidthCheck (virtualWidth: %i, clientWidth: %i)"),
+ width, clientWidth);
//
// Check min sizes
}
else
{
- if ( pg->HasFlag(wxPG_SPLITTER_AUTO_CENTER) )
- {
- if ( m_colWidths[i] >= highestColWidth )
- {
- highestColWidth = m_colWidths[i];
- reduceCol = i;
- }
- }
- else
- {
- reduceCol = i;
- }
+ // Always reduce the last column that is larger than minimum size
+ // (looks nicer, even with auto-centering enabled).
+ reduceCol = i;
}
}
for ( i=0; i<m_colWidths.size(); i++ )
colsWidth += m_colWidths[i];
-#ifdef __WXDEBUG__
- if ( debug )
- wxLogDebug(wxT(" HasVirtualWidth: %i colsWidth: %i"),(int)pg->HasVirtualWidth(),colsWidth);
-#endif
+ wxLogTrace("propgrid",
+ wxS(" HasVirtualWidth: %i colsWidth: %i"),
+ (int)pg->HasVirtualWidth(), colsWidth);
// Then mode-based requirement
if ( !pg->HasVirtualWidth() )
if ( colsWidth < width )
{
// Increase column
-#ifdef __WXDEBUG__
- if ( debug )
- wxLogDebug(wxT(" Adjust last column to %i"), m_colWidths[lastColumn] + widthHigher);
-#endif
+ wxLogTrace("propgrid",
+ wxS(" Adjust last column to %i"),
+ m_colWidths[lastColumn] + widthHigher);
m_colWidths[lastColumn] = m_colWidths[lastColumn] + widthHigher;
}
else if ( colsWidth > width )
// Reduce column
if ( reduceCol != -1 )
{
- #ifdef __WXDEBUG__
- if ( debug )
- wxLogDebug(wxT(" Reduce column %i (by %i)"), reduceCol, -widthHigher);
- #endif
+ wxLogTrace("propgrid",
+ wxT(" Reduce column %i (by %i)"),
+ reduceCol, -widthHigher);
+
// Reduce widest column, and recheck
m_colWidths[reduceCol] = m_colWidths[reduceCol] + widthHigher;
CheckColumnWidths();
pg->RecalculateVirtualSize();
}
-#ifdef __WXDEBUG__
- if ( debug )
- for ( i=0; i<m_colWidths.size(); i++ )
- wxLogDebug(wxT("col%i: %i"),i,m_colWidths[i]);
-#endif
+ for ( i=0; i<m_colWidths.size(); i++ )
+ {
+ wxLogTrace("propgrid", wxS("col%i: %i"), i, m_colWidths[i]);
+ }
// Auto center splitter
if ( !(pg->GetInternalFlags() & wxPG_FL_DONT_CENTER_SPLITTER) &&
{
p->SetValue(variant);
if ( m_selected==p && this==m_pPropGrid->GetState() )
- p->UpdateControl(m_pPropGrid->GetEditorControl());
+ m_pPropGrid->RefreshEditor();
}
return true;
{
p->SetValue(value);
if ( m_selected==p && this==m_pPropGrid->GetState() )
- p->UpdateControl(m_pPropGrid->GetEditorControl());
+ m_pPropGrid->RefreshEditor();
return true;
}
return false;
}
-// -----------------------------------------------------------------------
-
-void wxPropertyGridPageState::DoSetPropertyValueUnspecified( wxPGProperty* p )
-{
- wxCHECK_RET( p, wxT("invalid property id") );
-
- if ( !p->IsValueUnspecified() )
- {
- // Value should be set first - editor class methods may need it
- p->m_value.MakeNull();
-
- wxASSERT( m_pPropGrid );
-
- if ( m_pPropGrid->GetState() == this )
- {
- if ( m_pPropGrid->m_selected == p && m_pPropGrid->m_wndEditor )
- {
- p->GetEditorClass()->SetValueToUnspecified(p, m_pPropGrid->GetEditorControl());
- }
- }
-
- unsigned int i;
- for ( i = 0; i < p->GetChildCount(); i++ )
- DoSetPropertyValueUnspecified( p->Item(i) );
- }
-}
-
// -----------------------------------------------------------------------
// wxPropertyGridPageState property operations
// -----------------------------------------------------------------------
if ( wxStrcmp(current->GetType(), wxS("list")) == 0 )
{
DoSetPropertyValues( current->GetList(),
- p->IsCategory()?p:((wxPGProperty*)NULL)
+ p->IsCategory()?p:(NULL)
);
}
else
{
- #ifdef __WXDEBUG__
- if ( wxStrcmp(current->GetType(), p->GetValue().GetType()) != 0)
- {
- wxLogDebug(wxT("wxPropertyGridPageState::DoSetPropertyValues Warning: Setting value of property \"%s\" from variant"),
- p->GetName().c_str());
- }
- #endif
+ wxASSERT_LEVEL_2_MSG(
+ wxStrcmp(current->GetType(), p->GetValue().GetType()) == 0,
+ wxString::Format(
+ wxS("setting value of property \"%s\" from variant"),
+ p->GetName().c_str())
+ );
p->SetValue(*current);
}
m_pPropGrid->Thaw();
if ( this == m_pPropGrid->GetState() )
- {
- m_selected->UpdateControl(m_pPropGrid->GetEditorControl());
- }
+ m_pPropGrid->RefreshEditor();
}
}
// This will allow better behavior.
if ( scheduledParent == m_properties )
- scheduledParent = (wxPGProperty*) NULL;
+ scheduledParent = NULL;
if ( scheduledParent && !scheduledParent->IsCategory() )
{
}
}
-#ifdef __WXDEBUG__
+#if wxDEBUG_LEVEL
// Warn for identical names in debug mode.
if ( BaseGetPropertyByName(property->GetName()) &&
(!scheduledParent || scheduledParent->IsCategory()) )
{
- wxLogError(wxT("wxPropertyGrid: Warning - item with name \"%s\" already exists."),
- property->GetName().c_str());
+ wxFAIL_MSG(wxString::Format(
+ "wxPropertyGrid item with name \"%s\" already exists",
+ property->GetName()));
+
wxPGGlobalVars->m_warnings++;
}
-#endif
+#endif // wxDEBUG_LEVEL
// Make sure nothing is selected.
if ( propGrid )
{
wxPropertyCategory* cur_cat = m_currentCategory;
if ( property->IsCategory() )
- cur_cat = (wxPropertyCategory*) NULL;
+ cur_cat = NULL;
return DoInsert( cur_cat, -1, property );
}
if ( !res )
return m_currentCategory;
+ bool parentIsRoot = parent->IsRoot();
+ bool parentIsCategory = parent->IsCategory();
+
// Note that item must be added into current mode later.
// If parent is wxParentProperty, just stick it in...
// 1) Add to given category in given index.
// 2) Add as last item in m_abcArray.
- if ( !parent->IsCategory() && !parent->IsRoot() )
- {
- // Parent is wxParentingProperty: Just stick it in...
- parent->AddChild2( property, index );
- }
- else
+ if ( m_properties == &m_regularArray )
{
- // Parent is Category or Root.
+ // We are currently in Categorized mode
- if ( m_properties == &m_regularArray )
+ // Only add non-categories to m_abcArray.
+ if ( m_abcArray && !property->IsCategory() &&
+ (parentIsCategory || parentIsRoot) )
{
- // Categorized mode
-
- // Only add non-categories to m_abcArray.
- if ( m_abcArray && !property->IsCategory() )
- m_abcArray->AddChild2( property, -1, false );
-
- // Add to current mode.
- parent->AddChild2( property, index );
-
+ m_abcArray->DoAddChild( property, -1, false );
}
- else
- {
- // Non-categorized mode.
- if ( parent != m_properties )
- // Parent is category.
- parent->AddChild2( property, index, false );
- else
- // Parent is root.
- m_regularArray.AddChild2( property, -1, false );
-
- // Add to current mode (no categories).
- if ( !property->IsCategory() )
- m_abcArray->AddChild2( property, index );
- }
+ // Add to current mode.
+ parent->DoAddChild( property, index, true );
+ }
+ else
+ {
+ // We are currently in Non-categorized/Alphabetic mode
+
+ if ( parentIsCategory )
+ // Parent is category.
+ parent->DoAddChild( property, index, false );
+ else if ( parentIsRoot )
+ // Parent is root.
+ m_regularArray.DoAddChild( property, -1, false );
+
+ // Add to current mode
+ if ( !property->IsCategory() )
+ m_abcArray->DoAddChild( property, index, true );
}
// category stuff
// Only add name to hashmap if parent is root or category
if ( property->m_name.length() &&
- (parent->IsCategory() || parent->IsRoot()) )
+ (parentIsCategory || parentIsRoot) )
m_dictName[property->m_name] = (void*) property;
VirtualHeightChanged();
if ( item->IsCategory() )
{
if ( pwc == m_currentCategory )
- m_currentCategory = (wxPropertyCategory*) NULL;
+ m_currentCategory = NULL;
}
item->DeleteChildren();