void wxPropertyGridIteratorBase::Prev()
{
wxPGProperty* property = m_property;
- wxASSERT( property );
+ if ( !property )
+ return;
wxPGProperty* parent = property->GetParent();
wxASSERT( parent );
void wxPropertyGridIteratorBase::Next( bool iterateChildren )
{
wxPGProperty* property = m_property;
- wxASSERT( property );
+ if ( !property )
+ return;
if ( property->GetChildCount() &&
wxPG_ITERATOR_PARENTEXMASK_TEST(property, m_parentExMask) &&
m_properties = &m_regularArray;
m_abcArray = NULL;
m_currentCategory = NULL;
- m_selected = NULL;
m_width = 0;
m_virtualHeight = 0;
m_lastCaptionBottomnest = 1;
m_colWidths.push_back( wxPG_DEFAULT_SPLITTERX );
m_colWidths.push_back( wxPG_DEFAULT_SPLITTERX );
m_fSplitterX = wxPG_DEFAULT_SPLITTERX;
+
+ m_isSplitterPreSet = false;
+ m_dontCenterSplitter = false;
+
+ // By default, we only have the 'value' column editable
+ m_editableColumns.push_back(1);
}
// -----------------------------------------------------------------------
wxPGProperty* parent = p->GetParent();
if ( parent->IsCategory() || parent->IsRoot() )
{
- m_abcArray->AddChild2(p);
+ m_abcArray->DoAddChild(p);
p->m_parent = &m_regularArray;
}
}
}
else
{
- m_selected = NULL;
+ m_selection.clear();
}
m_regularArray.Empty();
void wxPropertyGridPageState::SetVirtualWidth( int width )
{
- wxASSERT( width >= 0 );
+ // Sometimes width less than 0 is offered. Let's make things easy for
+ // everybody and deal with it here.
+ if ( width < 0 )
+ width = 0;
+
wxPropertyGrid* pg = GetGrid();
int gw = pg->GetClientSize().x;
if ( width < gw )
widthChange = 0;
CheckColumnWidths(widthChange);
- if ( !(GetGrid()->GetInternalFlags() & wxPG_FL_SPLITTER_PRE_SET) &&
- (GetGrid()->GetInternalFlags() & wxPG_FL_DONT_CENTER_SPLITTER) )
+ if ( !m_isSplitterPreSet && m_dontCenterSplitter )
{
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 );
}
else
{
DoSetSplitterPosition( newWidth / 2 );
- GetGrid()->ClearInternalFlag(wxPG_FL_SPLITTER_PRE_SET);
+ m_isSplitterPreSet = false;
}
}
}
// -----------------------------------------------------------------------
-#if wxUSE_STL
-#include <algorithm>
-
-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().CmpNoCase( p2->GetLabel() ) < 0;
-}
-
-#else
-
static int wxPG_SortFunc_ByFunction(wxPGProperty **pp1, wxPGProperty **pp2)
{
wxPGProperty *p1 = *pp1;
return p1->GetLabel().CmpNoCase( p2->GetLabel() );
}
+#if 0
+//
+// For wxVector w/ wxUSE_STL=1, you would use code like this instead:
+//
+
+#include <algorithm>
+
+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().CmpNoCase( p2->GetLabel() ) < 0;
+}
#endif
void wxPropertyGridPageState::DoSortChildren( wxPGProperty* p,
&& !p->IsCategory() && !p->IsRoot() )
return;
-#if wxUSE_STL
+ if ( GetGrid()->GetSortFunction() )
+ p->m_children.Sort( wxPG_SortFunc_ByFunction );
+ else
+ p->m_children.Sort( wxPG_SortFunc_ByLabel );
+
+#if 0
+ //
+ // For wxVector w/ wxUSE_STL=1, you would use code like this instead:
+ //
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
- if ( GetGrid()->GetSortFunction() )
- p->m_children.Sort( wxPG_SortFunc_ByFunction );
- else
- p->m_children.Sort( wxPG_SortFunc_ByLabel );
#endif
// Fix indices
// -----------------------------------------------------------------------
-wxPropertyGridHitTestResult wxPropertyGridPageState::HitTest( const wxPoint&pt ) const
+wxPropertyGridHitTestResult
+wxPropertyGridPageState::HitTest( const wxPoint&pt ) const
{
wxPropertyGridHitTestResult result;
- result.column = HitTestH( pt.x, &result.splitter, &result.splitterHitOffset );
- result.property = DoGetItemAtY( pt.y );
+ result.m_column = HitTestH( pt.x, &result.m_splitter,
+ &result.m_splitterHitOffset );
+ result.m_property = DoGetItemAtY( pt.y );
return result;
}
if ( col == 0 )
w += ( ((int)p->m_depth-1) * pg->m_subgroup_extramargin );
- //
- // TODO: Add bitmap support.
+ // account for the bitmap
+ if ( col == 1 )
+ w += p->GetImageOffset(pg->GetImageRect(p, -1).GetWidth());
+
w += (wxPG_XBEFORETEXT*2);
return wxPG_DRAG_MARGIN;
}
-void wxPropertyGridPageState::PropagateColSizeDec( int column, int decrease, int dir )
+void wxPropertyGridPageState::PropagateColSizeDec( int column,
+ int decrease,
+ int dir )
{
int origWidth = m_colWidths[column];
m_colWidths[column] -= decrease;
PropagateColSizeDec( column, more, dir );
}
-void wxPropertyGridPageState::DoSetSplitterPosition( int newXPos, int splitterColumn, bool WXUNUSED(allPages), bool fromAutoCenter )
+void wxPropertyGridPageState::DoSetSplitterPosition( int newXPos,
+ int splitterColumn,
+ int flags )
{
wxPropertyGrid* pg = GetGrid();
if ( splitterColumn == 0 )
m_fSplitterX = (double) newXPos;
- if ( !fromAutoCenter )
+ if ( !(flags & wxPG_SPLITTER_FROM_AUTO_CENTER) &&
+ !(flags & wxPG_SPLITTER_FROM_EVENT) )
{
// Don't allow initial splitter auto-positioning after this.
- if ( pg->GetState() == this )
- pg->SetInternalFlag(wxPG_FL_SPLITTER_PRE_SET);
+ m_isSplitterPreSet = true;
CheckColumnWidths();
}
DoSetSplitterPosition( maxW );
}
- pg->SetInternalFlag(wxPG_FL_DONT_CENTER_SPLITTER);
+ m_dontCenterSplitter = true;
}
wxSize wxPropertyGridPageState::DoFitColumns( bool WXUNUSED(allowGridResize) )
int remaining = m_width - accWid;
m_colWidths[GetColumnCount()-1] += remaining;
- pg->SetInternalFlag(wxPG_FL_DONT_CENTER_SPLITTER);
+ m_dontCenterSplitter = true;
int firstSplitterX = marginWidth + m_colWidths[0];
m_fSplitterX = (double) firstSplitterX;
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) &&
- m_colWidths.size() == 2 )
+ if ( !m_dontCenterSplitter && m_colWidths.size() == 2 )
{
float centerX = (float)(pg->m_width/2);
float splitterX;
}
}
- DoSetSplitterPosition((int)splitterX, 0, false, true);
+ DoSetSplitterPosition((int)splitterX, 0,
+ wxPG_SPLITTER_FROM_AUTO_CENTER);
m_fSplitterX = splitterX; // needed to retain accuracy
}
wxASSERT( colCount >= 2 );
m_colWidths.SetCount( colCount, wxPG_DRAG_MARGIN );
if ( m_colWidths.size() > (unsigned int)colCount )
- m_colWidths.RemoveAt( m_colWidths.size(), m_colWidths.size() - colCount );
+ m_colWidths.RemoveAt( m_colWidths.size()-1,
+ m_colWidths.size() - colCount );
if ( m_pPropGrid->GetState() == this )
m_pPropGrid->RecalculateVirtualSize();
return col;
}
+bool wxPropertyGridPageState::ArePropertiesAdjacent( wxPGProperty* prop1,
+ wxPGProperty* prop2,
+ int iterFlags ) const
+{
+ const wxPGProperty* ap1 =
+ wxPropertyGridConstIterator::OneStep(this,
+ iterFlags,
+ prop1,
+ 1);
+ if ( ap1 && ap1 == prop2 )
+ return true;
+
+ const wxPGProperty* ap2 =
+ wxPropertyGridConstIterator::OneStep(this,
+ iterFlags,
+ prop1,
+ -1);
+ if ( ap2 && ap2 == prop2 )
+ return true;
+
+ return false;
+}
+
// -----------------------------------------------------------------------
// wxPropertyGridPageState property value setting and getting
// -----------------------------------------------------------------------
if ( res )
{
p->SetValue(variant);
- if ( m_selected==p && this==m_pPropGrid->GetState() )
+ if ( p == m_pPropGrid->GetSelection() &&
+ this == m_pPropGrid->GetState() )
m_pPropGrid->RefreshEditor();
}
if ( p )
{
p->SetValue(value);
- if ( m_selected==p && this==m_pPropGrid->GetState() )
+ if ( p == m_pPropGrid->GetSelection() &&
+ this == m_pPropGrid->GetState() )
m_pPropGrid->RefreshEditor();
return true;
// wxPropertyGridPageState property operations
// -----------------------------------------------------------------------
+bool wxPropertyGridPageState::DoIsPropertySelected( wxPGProperty* prop ) const
+{
+ const wxArrayPGProperty& selection = m_selection;
+
+ for ( unsigned int i=0; i<selection.size(); i++ )
+ {
+ if ( selection[i] == prop )
+ return true;
+ }
+
+ return false;
+}
+
+// -----------------------------------------------------------------------
+
+void wxPropertyGridPageState::DoRemoveFromSelection( wxPGProperty* prop )
+{
+ for ( unsigned int i=0; i<m_selection.size(); i++ )
+ {
+ if ( m_selection[i] == prop )
+ {
+ wxPropertyGrid* pg = m_pPropGrid;
+ if ( i == 0 && pg->GetState() == this )
+ {
+ // If first item (ie. one with the active editor) was
+ // deselected, then we need to take some extra measures.
+ wxArrayPGProperty sel = m_selection;
+ sel.erase( sel.begin() + i );
+
+ wxPGProperty* newFirst;
+ if ( sel.size() )
+ newFirst = sel[0];
+ else
+ newFirst = NULL;
+
+ pg->DoSelectProperty(newFirst,
+ wxPG_SEL_DONT_SEND_EVENT);
+
+ m_selection = sel;
+
+ pg->Refresh();
+ }
+ else
+ {
+ m_selection.erase( m_selection.begin() + i );
+ }
+ return;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
bool wxPropertyGridPageState::DoCollapse( wxPGProperty* p )
{
wxCHECK_MSG( p, false, wxT("invalid property id") );
if ( this == m_pPropGrid->GetState() )
return m_pPropGrid->DoSelectProperty( p, flags );
- m_selected = p;
+ DoSetSelection(p);
return true;
}
}
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);
}
}
}
-#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 )
if ( m_abcArray && !property->IsCategory() &&
(parentIsCategory || parentIsRoot) )
{
- m_abcArray->AddChild2( property, -1, false );
+ m_abcArray->DoAddChild( property, -1, false );
}
// Add to current mode.
- parent->AddChild2( property, index, true );
+ parent->DoAddChild( property, index, true );
}
else
{
if ( parentIsCategory )
// Parent is category.
- parent->AddChild2( property, index, false );
+ parent->DoAddChild( property, index, false );
else if ( parentIsRoot )
// Parent is root.
- m_regularArray.AddChild2( property, -1, false );
+ m_regularArray.DoAddChild( property, -1, false );
// Add to current mode
if ( !property->IsCategory() )
- m_abcArray->AddChild2( property, index, true );
+ m_abcArray->DoAddChild( property, index, true );
}
// category stuff
wxCHECK_RET( !parent->HasFlag(wxPG_PROP_AGGREGATE),
wxT("wxPropertyGrid: Do not attempt to remove sub-properties.") );
+ wxASSERT( item->GetParentState() == this );
+
+ wxPropertyGrid* pg = GetGrid();
+
+ if ( DoIsPropertySelected(item) )
+ {
+ if ( pg && pg->GetState() == this )
+ {
+ pg->DoRemoveFromSelection(item,
+ wxPG_SEL_DELETING|wxPG_SEL_NOVALIDATE);
+ }
+ else
+ {
+ DoRemoveFromSelection(item);
+ }
+ }
+
+ item->SetFlag(wxPG_PROP_BEING_DELETED);
+
// Delete children
if ( item->GetChildCount() && !item->HasFlag(wxPG_PROP_AGGREGATE) )
{
}
}
- if ( item->GetBaseName().length() &&
+ if ( item->GetBaseName().length() &&
(parent->IsCategory() || parent->IsRoot()) )
m_dictName.erase(item->GetBaseName());
+ // We need to clear parent grid's m_propHover, if it matches item
+ if ( pg && pg->m_propHover == item )
+ pg->m_propHover = NULL;
+
// We can actually delete it now
if ( doDelete )
delete item;