// Author: Jaakko Salli
// Modified by:
// Created: 2008-08-24
-// RCS-ID: $Id:
+// RCS-ID: $Id$
// Copyright: (c) Jaakko Salli
// Licence: wxWindows license
/////////////////////////////////////////////////////////////////////////////
#pragma hdrstop
#endif
+#if wxUSE_PROPGRID
+
#ifndef WX_PRECOMP
#include "wx/defs.h"
#include "wx/object.h"
#include "wx/panel.h"
#include "wx/dc.h"
#include "wx/dcmemory.h"
- #include "wx/button.h"
#include "wx/pen.h"
#include "wx/brush.h"
- #include "wx/cursor.h"
- #include "wx/dialog.h"
- #include "wx/settings.h"
- #include "wx/msgdlg.h"
- #include "wx/choice.h"
- #include "wx/stattext.h"
- #include "wx/scrolwin.h"
- #include "wx/dirdlg.h"
- #include "wx/layout.h"
- #include "wx/sizer.h"
- #include "wx/textdlg.h"
- #include "wx/filedlg.h"
- #include "wx/statusbr.h"
#include "wx/intl.h"
- #include "wx/frame.h"
#include "wx/stopwatch.h"
#endif
// This define is necessary to prevent macro clearing
#define __wxPG_SOURCE_FILE__
-#include <wx/propgrid/propgridpagestate.h>
-#include <wx/propgrid/propgrid.h>
-#include <wx/propgrid/editors.h>
-
-#include <typeinfo>
+#include "wx/propgrid/propgridpagestate.h"
+#include "wx/propgrid/propgrid.h"
+#include "wx/propgrid/editors.h"
#define wxPG_DEFAULT_SPLITTERX 110
void wxPropertyGridIteratorBase::Init( wxPropertyGridPageState* state, int flags, int startPos, int dir )
{
- wxPGProperty* property;
+ wxPGProperty* property = NULL;
if ( startPos == wxTOP )
{
- property = NULL;
if ( dir == 0 )
dir = 1;
}
}
else
{
- wxASSERT_MSG( false, wxT("Only supported stating positions are wxTOP and wxBOTTOM") );
- property = NULL;
+ wxFAIL_MSG("Only supported starting positions are wxTOP and wxBOTTOM");
}
Init( state, flags, property, dir );
if ( m_properties->GetChildCount() )
{
- // Copy items.
- wxPropertyGridIterator it( this, wxPG_ITERATE_DEFAULT|wxPG_ITERATE_CATEGORIES );
+ //
+ // Prepare m_abcArray
+ wxPropertyGridIterator it( this, wxPG_ITERATE_PROPERTIES );
for ( ; !it.AtEnd(); it.Next() )
{
wxPGProperty* p = it.GetProperty();
wxPGProperty* parent = p->GetParent();
- if ( p->HasFlag(wxPG_PROP_MISC_PARENT) &&
- ( parent == m_properties || (parent->IsCategory() || parent->IsRoot()) ) )
+ if ( parent->IsCategory() || parent->IsRoot() )
{
- m_abcArray->AddChild2( p );
+ m_abcArray->AddChild2(p);
p->m_parent = &m_regularArray;
}
}
return (wxPGProperty*) NULL;
}
+// -----------------------------------------------------------------------
+
+void wxPropertyGridPageState::DoSetPropertyName( wxPGProperty* p,
+ const wxString& newName )
+{
+ wxCHECK_RET( p, wxT("invalid property id") );
+
+ wxPGProperty* parent = p->GetParent();
+
+ if ( parent->IsCategory() || parent->IsRoot() )
+ {
+ if ( p->GetBaseName().length() )
+ m_dictName.erase( p->GetBaseName() );
+ if ( newName.length() )
+ m_dictName[newName] = (void*) p;
+ }
+
+ p->DoSetName(newName);
+}
+
// -----------------------------------------------------------------------
// wxPropertyGridPageState global operations
// -----------------------------------------------------------------------
// NB: Nowadays only needed for alphabetic/categoric mode switching.
// -----------------------------------------------------------------------
-#define II_INVALID_I 0x00FFFFFF
+//#define II_INVALID_I 0x00FFFFFF
#define ITEM_ITERATION_VARIABLES \
wxPGProperty* parent; \
parent = m_properties; \
i = 0;
+#if 0
#define ITEM_ITERATION_INIT(startparent, startindex, state) \
parent = startparent; \
i = (unsigned int)startindex; \
parent = state->m_properties; \
i = 0; \
}
+#endif
#define ITEM_ITERATION_LOOP_BEGIN \
do \
// -----------------------------------------------------------------------
-static int wxPG_SortFunc(void **p1, void **p2)
+#if wxUSE_STL
+#include <algorithm>
+
+static bool wxPG_SortFunc(wxPGProperty *p1, wxPGProperty *p2)
+{
+ return p1->GetLabel() < p2->GetLabel();
+}
+
+#else
+
+static int wxPG_SortFunc(wxPGProperty **p1, wxPGProperty **p2)
{
- wxPGProperty *pp1 = *((wxPGProperty**)p1);
- wxPGProperty *pp2 = *((wxPGProperty**)p2);
+ wxPGProperty *pp1 = *p1;
+ wxPGProperty *pp2 = *p2;
return pp1->GetLabel().compare( pp2->GetLabel() );
}
+#endif
+
void wxPropertyGridPageState::SortChildren( wxPGProperty* p )
{
if ( !p )
if ( pwc->GetChildCount() < 1 )
return;
+#if wxUSE_STL
+ std::sort(pwc->m_children.begin(), pwc->m_children.end(), wxPG_SortFunc);
+#else
pwc->m_children.Sort( wxPG_SortFunc );
+#endif
// Fix indexes
- pwc->FixIndexesOfChildren();
+ pwc->FixIndicesOfChildren();
}
wxPGProperty* p = pwc->Item(i);
if ( !p->IsCategory() )
{
- dc.GetTextExtent( p->GetColumnText(col), &w, &h );
+ const wxPGCell* cell = NULL;
+ wxString text;
+ p->GetDisplayInfo(col, -1, 0, &text, &cell);
+ dc.GetTextExtent(text, &w, &h);
if ( col == 0 )
w += ( ((int)p->m_depth-1) * pg->m_subgroup_extramargin );
int reduceCol = -1;
int highestColWidth = 0;
- bool minimizedCols = false;
-
#ifdef __WXDEBUG__
if ( debug )
wxLogDebug(wxT("ColumnWidthCheck (virtualWidth: %i, clientWidth: %i)"), width, clientWidth);
if ( m_colWidths[i] <= min )
{
m_colWidths[i] = min;
- minimizedCols = true;
}
else
{
if ( colsWidth < width )
{
// Increase column
- #ifdef __WXDEBUG__
- if ( debug )
- wxLogDebug(wxT(" Adjust last column to %i"), m_colWidths[lastColumn] + widthHigher);
- #endif
+#ifdef __WXDEBUG__
+ if ( debug )
+ wxLogDebug(wxT(" Adjust last column to %i"), m_colWidths[lastColumn] + widthHigher);
+#endif
m_colWidths[lastColumn] = m_colWidths[lastColumn] + widthHigher;
}
else if ( colsWidth > width )
{
if ( p )
{
- int flags = wxPG_REPORT_ERROR|wxPG_FULL_VALUE;
+ int flags = wxPG_REPORT_ERROR|wxPG_FULL_VALUE|wxPG_PROGRAMMATIC_VALUE;
wxVariant variant = p->GetValueRef();
bool res;
//
// Second pass for special entries
- for ( node = list.begin(); node != list.end(); node++ )
+ for ( node = list.begin(); node != list.end(); ++node )
{
wxVariant *current = (wxVariant*)*node;
if ( numSpecialEntries )
{
- for ( node = list.begin(); node != list.end(); node++ )
+ for ( node = list.begin(); node != list.end(); ++node )
{
wxVariant *current = (wxVariant*)*node;
wxPGProperty* foundProp = BaseGetPropertyByName(propName);
if ( foundProp )
{
- wxASSERT( wxPGIsVariantType(*current, list) );
+ wxASSERT( current->GetType() == wxPG_VARIANT_TYPE_LIST );
wxVariantList& list2 = current->GetList();
wxVariantList::const_iterator node2;
- for ( node2 = list2.begin(); node2 != list2.end(); node2++ )
+ for ( node2 = list2.begin(); node2 != list2.end(); ++node2 )
{
wxVariant *attr = (wxVariant*)*node2;
foundProp->SetAttribute( attr->GetName(), *attr );
// wxPropertyGridPageState property adding and removal
// -----------------------------------------------------------------------
-int wxPropertyGridPageState::PrepareToAddItem( wxPGProperty* property,
- wxPGProperty* scheduledParent )
+bool wxPropertyGridPageState::PrepareToAddItem( wxPGProperty* property,
+ wxPGProperty* scheduledParent )
{
wxPropertyGrid* propGrid = m_pPropGrid;
{
delete property;
m_currentCategory = pwc;
- return 2; // Tells the caller what we did.
+ return false;
}
}
}
#endif
// Make sure nothing is selected.
- if ( propGrid && propGrid->m_selected )
- {
- bool selRes = propGrid->ClearSelection();
- wxPG_CHECK_MSG_DBG( selRes,
- -1,
- wxT("failed to deselect a property (editor probably had invalid value)") );
- }
+ if ( propGrid )
+ propGrid->ClearSelection(false);
- if ( scheduledParent )
- {
- // Use parent's colours.
- property->m_bgColIndex = scheduledParent->m_bgColIndex;
- property->m_fgColIndex = scheduledParent->m_fgColIndex;
-
- // 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);
- }
+ // NULL parent == root parent
+ if ( !scheduledParent )
+ scheduledParent = DoGetRoot();
- // 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;
- }
+ property->m_parent = scheduledParent;
- if ( propGrid && (propGrid->GetWindowStyleFlag() & wxPG_LIMITED_EDITING) )
- property->m_flags |= wxPG_PROP_NOEDITOR;
-
- if ( !property->IsCategory() )
- {
- // This is not a category.
+ property->InitAfterAdded(this, propGrid);
- //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
+ if ( property->IsCategory() )
{
- // This is a category.
+ wxPropertyCategory* pc = wxStaticCast(property, wxPropertyCategory);
- // depth
- unsigned char depth = 1;
- if ( scheduledParent )
- {
- depth = scheduledParent->m_depth + 1;
- }
- property->m_depth = depth;
- property->m_depthBgCol = depth;
-
- m_currentCategory = (wxPropertyCategory*)property;
+ m_currentCategory = pc;
- 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;
}
// -----------------------------------------------------------------------
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.
// 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.
m_regularArray.AddChild2( property, -1, false );
// Add to current mode (no categories).
- if ( parenting <= 0 )
+ if ( !property->IsCategory() )
m_abcArray->AddChild2( property, index );
}
}
}
// Only add name to hashmap if parent is root or category
- if ( (parent->IsCategory() || parent->IsRoot()) && property->m_name.length() )
+ if ( property->m_name.length() &&
+ (parent->IsCategory() || parent->IsRoot()) )
m_dictName[property->m_name] = (void*) property;
VirtualHeightChanged();
// -----------------------------------------------------------------------
-void wxPropertyGridPageState::DoDelete( wxPGProperty* item )
+void wxPropertyGridPageState::DoDelete( wxPGProperty* item, bool doDelete )
{
wxCHECK_RET( item->GetParent(),
wxT("this property was already deleted") );
wxCHECK_RET( item != &m_regularArray && item != m_abcArray,
wxT("wxPropertyGrid: Do not attempt to remove the root item.") );
- size_t i;
unsigned int indinparent = item->GetIndexInParent();
wxPGProperty* pwc = (wxPGProperty*)item;
+ wxPGProperty* parent = item->GetParent();
- wxCHECK_RET( !item->GetParent()->HasFlag(wxPG_PROP_AGGREGATE),
+ wxCHECK_RET( !parent->HasFlag(wxPG_PROP_AGGREGATE),
wxT("wxPropertyGrid: Do not attempt to remove sub-properties.") );
- if ( item->IsCategory() )
+ // Delete children
+ if ( item->GetChildCount() && !item->HasFlag(wxPG_PROP_AGGREGATE) )
{
// deleting a category
-
- // erase category entries from the hash table
- for ( i=0; i<pwc->GetChildCount(); i++ )
+ if ( item->IsCategory() )
{
- wxPGProperty* sp = pwc->Item( i );
- if ( sp->GetBaseName().Len() ) m_dictName.erase(sp->GetBaseName());
+ if ( pwc == m_currentCategory )
+ m_currentCategory = (wxPropertyCategory*) NULL;
}
- if ( pwc == m_currentCategory )
- m_currentCategory = (wxPropertyCategory*) NULL;
-
- if ( m_abcArray )
- {
- // Remove children from non-categorized array.
- for ( i=0; i<pwc->GetChildCount(); i++ )
- {
- wxPGProperty * p = pwc->Item( i );
- wxASSERT( p != NULL );
- if ( !p->IsCategory() )
- m_abcArray->m_children.Remove( p );
- }
-
- if ( IsInNonCatMode() )
- m_abcArray->FixIndexesOfChildren();
- }
+ item->DeleteChildren();
}
if ( !IsInNonCatMode() )
{
// categorized mode - non-categorized array
- // Remove from non-cat array, but only if parent is in it
- if ( !item->IsCategory() && item->GetParent()->IsCategory() )
+ // Remove from non-cat array
+ if ( !item->IsCategory() &&
+ (parent->IsCategory() || parent->IsRoot()) )
{
if ( m_abcArray )
- {
- m_abcArray->m_children.Remove( item );
- }
+ m_abcArray->RemoveChild(item);
}
// categorized mode - categorized array
- item->m_parent->m_children.RemoveAt(indinparent);
- item->m_parent->FixIndexesOfChildren(/*indinparent*/);
+ wxArrayPGProperty& parentsChildren = parent->m_children;
+ parentsChildren.erase( parentsChildren.begin() + indinparent );
+ item->m_parent->FixIndicesOfChildren();
}
else
{
}
}
}
- cat_parent->m_children.RemoveAt(cat_index);
+ cat_parent->m_children.erase(cat_parent->m_children.begin()+cat_index);
// non-categorized mode - non-categorized array
if ( !item->IsCategory() )
{
wxASSERT( item->m_parent == m_abcArray );
- item->m_parent->m_children.RemoveAt(indinparent);
- item->m_parent->FixIndexesOfChildren(indinparent);
+ wxArrayPGProperty& parentsChildren = item->m_parent->m_children;
+ parentsChildren.erase(parentsChildren.begin() + indinparent);
+ item->m_parent->FixIndicesOfChildren(indinparent);
}
}
- if ( item->GetBaseName().Len() ) m_dictName.erase(item->GetBaseName());
+ if ( item->GetBaseName().length() &&
+ (parent->IsCategory() || parent->IsRoot()) )
+ m_dictName.erase(item->GetBaseName());
// We can actually delete it now
- delete item;
+ if ( doDelete )
+ delete item;
m_itemsAdded = 1; // Not a logical assignment (but required nonetheless).
}
// -----------------------------------------------------------------------
+
+#endif // wxUSE_PROPGRID