]> git.saurik.com Git - wxWidgets.git/blobdiff - src/propgrid/propgrid.cpp
Add samples files missing from distribution.
[wxWidgets.git] / src / propgrid / propgrid.cpp
index 190021d63e7af19560315486968553af75f392f9..b323f7f4cf6158fc8aa875d7ca97832c9153a8ab 100644 (file)
@@ -63,8 +63,6 @@
 
 #include "wx/timer.h"
 #include "wx/dcbuffer.h"
-#include "wx/clipbrd.h"
-#include "wx/dataobj.h"
 
 #ifdef __WXMSW__
     #include "wx/msw/private.h"
 
 
 //#define wxPG_TEXT_INDENT                4 // For the wxComboControl
-#define wxPG_ALLOW_CLIPPING             1 // If 1, GetUpdateRegion() in OnPaint event handler is not ignored
+//#define wxPG_ALLOW_CLIPPING             1 // If 1, GetUpdateRegion() in OnPaint event handler is not ignored
 #define wxPG_GUTTER_DIV                 3 // gutter is max(iconwidth/gutter_div,gutter_min)
 #define wxPG_GUTTER_MIN                 3 // gutter before and after image of [+] or [-]
 #define wxPG_YSPACING_MIN               1
 #define wxPG_DEFAULT_VSPACING           2 // This matches .NET propertygrid's value,
                                           // but causes normal combobox to spill out under MSW
 
-#define wxPG_OPTIMAL_WIDTH              200 // Arbitrary
+//#define wxPG_OPTIMAL_WIDTH              200 // Arbitrary
 
-#define wxPG_MIN_SCROLLBAR_WIDTH        10 // Smallest scrollbar width on any platform
+//#define wxPG_MIN_SCROLLBAR_WIDTH        10 // Smallest scrollbar width on any platform
                                            // Must be larger than largest control border
                                            // width * 2.
 
 
 //#define wxPG_NAT_CHOICE_BORDER_ANY   0
 
-#define wxPG_HIDER_BUTTON_HEIGHT        25
+//#define wxPG_HIDER_BUTTON_HEIGHT        25
 
 #define wxPG_PIXELS_PER_UNIT            m_lineHeight
 
   #define m_iconHeight m_iconWidth
 #endif
 
-#define wxPG_TOOLTIP_DELAY              1000
+//#define wxPG_TOOLTIP_DELAY              1000
 
 // -----------------------------------------------------------------------
 
@@ -154,7 +152,16 @@ public:
 IMPLEMENT_DYNAMIC_CLASS(wxPGGlobalVarsClassManager, wxModule)
 
 
-wxPGGlobalVarsClass* wxPGGlobalVars = (wxPGGlobalVarsClass*) NULL;
+// When wxPG is loaded dynamically after the application is already running
+// then the built-in module system won't pick this one up.  Add it manually.
+void wxPGInitResourceModule()
+{
+    wxModule* module = new wxPGGlobalVarsClassManager;
+    module->Init();
+    wxModule::RegisterModule(module);
+}
+
+wxPGGlobalVarsClass* wxPGGlobalVars = NULL;
 
 
 wxPGGlobalVarsClass::wxPGGlobalVarsClass()
@@ -164,7 +171,7 @@ wxPGGlobalVarsClass::wxPGGlobalVarsClass()
     m_boolChoices.Add(_("False"));
     m_boolChoices.Add(_("True"));
 
-    m_fontFamilyChoices = (wxPGChoices*) NULL;
+    m_fontFamilyChoices = NULL;
 
     m_defaultRenderer = new wxPGDefaultRenderer();
 
@@ -176,7 +183,7 @@ wxPGGlobalVarsClass::wxPGGlobalVarsClass()
 
     wxVariant v;
 
-       // Prepare some shared variants
+    // Prepare some shared variants
     m_vEmptyString = wxString();
     m_vZero = (long) 0;
     m_vMinusOne = (long) -1;
@@ -188,14 +195,13 @@ wxPGGlobalVarsClass::wxPGGlobalVarsClass()
     m_strlong = wxS("long");
     m_strbool = wxS("bool");
     m_strlist = wxS("list");
+    m_strDefaultValue = wxS("DefaultValue");
     m_strMin = wxS("Min");
     m_strMax = wxS("Max");
     m_strUnits = wxS("Units");
     m_strInlineHelp = wxS("InlineHelp");
 
-#ifdef __WXDEBUG__
     m_warnings = 0;
-#endif
 }
 
 
@@ -231,46 +237,6 @@ void wxPropertyGridInitGlobalsIfNeeded()
 {
 }
 
-// -----------------------------------------------------------------------
-// wxPGTLWHandler
-//   Intercepts Close-events sent to wxPropertyGrid's top-level parent,
-//   and tries to commit property value.
-// -----------------------------------------------------------------------
-
-class wxPGTLWHandler : public wxEvtHandler
-{
-public:
-
-    wxPGTLWHandler( wxPropertyGrid* pg )
-        : wxEvtHandler()
-    {
-        m_pg = pg;
-    }
-
-protected:
-
-    void OnClose( wxCloseEvent& event )
-    {
-        // ClearSelection forces value validation/commit.
-        if ( event.CanVeto() && !m_pg->ClearSelection() )
-        {
-            event.Veto();
-            return;
-        }
-
-        event.Skip();
-    }
-
-private:
-    wxPropertyGrid*     m_pg;
-
-    DECLARE_EVENT_TABLE()
-};
-
-BEGIN_EVENT_TABLE(wxPGTLWHandler, wxEvtHandler)
-    EVT_CLOSE(wxPGTLWHandler::OnClose)
-END_EVENT_TABLE()
-
 // -----------------------------------------------------------------------
 // wxPGCanvas
 // -----------------------------------------------------------------------
@@ -364,6 +330,12 @@ void wxPGCanvas::OnPaint( wxPaintEvent& WXUNUSED(event) )
     // Update everything inside the box
     wxRect r = GetUpdateRegion().GetBox();
 
+    // FIXME: This is just a workaround for a bug that causes splitters not
+    //        to paint when other windows are being dragged over the grid.
+    wxRect fullRect = GetRect();
+    r.x = fullRect.x;
+    r.width = fullRect.width;
+
     // Repaint this rectangle
     pg->DrawItems( dc, r.y, r.y + r.height, &r );
 
@@ -454,14 +426,14 @@ void wxPropertyGrid::Init1()
         wxPropertyGrid::RegisterDefaultEditors();
 
     m_iFlags = 0;
-    m_pState = (wxPropertyGridPageState*) NULL;
-    m_wndEditor = m_wndEditor2 = (wxWindow*) NULL;
-    m_selected = (wxPGProperty*) NULL;
+    m_pState = NULL;
+    m_wndEditor = m_wndEditor2 = NULL;
+    m_selected = NULL;
     m_selColumn = -1;
-    m_propHover = (wxPGProperty*) NULL;
+    m_propHover = NULL;
     m_eventObject = this;
-    m_curFocused = (wxWindow*) NULL;
-    m_tlwHandler = NULL;
+    m_curFocused = NULL;
+    m_sortFunction = NULL;
     m_inDoPropertyChanged = 0;
     m_inCommitChangesFromEditor = 0;
     m_inDoSelectProperty = 0;
@@ -487,14 +459,14 @@ void wxPropertyGrid::Init1()
     m_canvas = NULL;
 
 #if wxPG_DOUBLE_BUFFER
-    m_doubleBuffer = (wxBitmap*) NULL;
+    m_doubleBuffer = NULL;
 #endif
 
 #ifndef wxPG_ICON_WIDTH
-       m_expandbmp = NULL;
-       m_collbmp = NULL;
-       m_iconWidth = 11;
-       m_iconHeight = 11;
+    m_expandbmp = NULL;
+    m_collbmp = NULL;
+    m_iconWidth = 11;
+    m_iconHeight = 11;
 #else
     m_iconWidth = wxPG_ICON_WIDTH;
 #endif
@@ -551,31 +523,22 @@ void wxPropertyGrid::Init2()
 
 #ifndef wxPG_ICON_WIDTH
     // create two bitmap nodes for drawing
-       m_expandbmp = new wxBitmap(expand_xpm);
-       m_collbmp = new wxBitmap(collapse_xpm);
+    m_expandbmp = new wxBitmap(expand_xpm);
+    m_collbmp = new wxBitmap(collapse_xpm);
 
-       // calculate average font height for bitmap centering
+    // calculate average font height for bitmap centering
 
-       m_iconWidth = m_expandbmp->GetWidth();
-       m_iconHeight = m_expandbmp->GetHeight();
+    m_iconWidth = m_expandbmp->GetWidth();
+    m_iconHeight = m_expandbmp->GetHeight();
 #endif
 
     m_curcursor = wxCURSOR_ARROW;
     m_cursorSizeWE = new wxCursor( wxCURSOR_SIZEWE );
 
-       // adjust bitmap icon y position so they are centered
+    // adjust bitmap icon y position so they are centered
     m_vspacing = wxPG_DEFAULT_VSPACING;
 
-    if ( !m_font.Ok() )
-    {
-        wxFont useFont = wxScrolledWindow::GetFont();
-        wxScrolledWindow::SetOwnFont( useFont );
-    }
-    else
-    {
-        // This should be otherwise called by SetOwnFont
-           CalculateFontAndBitmapStuff( wxPG_DEFAULT_VSPACING );
-    }
+    CalculateFontAndBitmapStuff( wxPG_DEFAULT_VSPACING );
 
     // Allocate cell datas indirectly by calling setter
     m_propertyDefaultCell.SetBgCol(*wxBLACK);
@@ -586,15 +549,15 @@ void wxPropertyGrid::Init2()
     // This helps with flicker
     SetBackgroundStyle( wxBG_STYLE_CUSTOM );
 
-    // Hook the TLW
-    wxPGTLWHandler* handler = new wxPGTLWHandler(this);
-    m_tlp = ::wxGetTopLevelParent(this);
-    m_tlwHandler = handler;
-    m_tlp->PushEventHandler(handler);
+    // Hook the top-level parent
+    m_tlp = NULL;
+    m_tlpClosed = NULL;
+    m_tlpClosedTime = 0;
+    OnTLPChanging(::wxGetTopLevelParent(this));
 
-       // set virtual size to this window size
+    // set virtual size to this window size
     wxSize wndsize = GetSize();
-       SetVirtualSize(wndsize.GetWidth(), wndsize.GetWidth());
+    SetVirtualSize(wndsize.GetWidth(), wndsize.GetWidth());
 
     m_timeCreated = ::wxGetLocalTimeMillis();
 
@@ -627,22 +590,20 @@ wxPropertyGrid::~wxPropertyGrid()
     if ( m_iFlags & wxPG_FL_MOUSE_CAPTURED )
         m_canvas->ReleaseMouse();
 
-    wxPGTLWHandler* handler = (wxPGTLWHandler*) m_tlwHandler;
-    m_tlp->RemoveEventHandler(handler);
-    delete handler;
+    // Call with NULL to disconnect event handling
+    OnTLPChanging(NULL);
 
-#ifdef __WXDEBUG__
-    if ( IsEditorsValueModified() )
-        ::wxMessageBox(wxS("Most recent change in property editor was lost!!!\n\n(if you don't want this to happen, close your frames and dialogs using Close(false).)"),
-                       wxS("wxPropertyGrid Debug Warning") );
-#endif
+    wxASSERT_MSG( !IsEditorsValueModified(),
+                  wxS("Most recent change in property editor was lost!!! ")
+                  wxS("(if you don't want this to happen, close your frames ")
+                  wxS("and dialogs using Close(false).)") );
 
 #if wxPG_DOUBLE_BUFFER
     if ( m_doubleBuffer )
         delete m_doubleBuffer;
 #endif
 
-    //m_selected = (wxPGProperty*) NULL;
+    //m_selected = NULL;
 
     if ( m_iFlags & wxPG_FL_CREATEDSTATE )
         delete m_pState;
@@ -650,8 +611,8 @@ wxPropertyGrid::~wxPropertyGrid()
     delete m_cursorSizeWE;
 
 #ifndef wxPG_ICON_WIDTH
-       delete m_expandbmp;
-       delete m_collbmp;
+    delete m_expandbmp;
+    delete m_collbmp;
 #endif
 
     // Delete common value records
@@ -727,7 +688,7 @@ void wxPropertyGrid::SetWindowStyleFlag( long style )
             //
             // Tooltips disabled
             //
-            m_canvas->SetToolTip( (wxToolTip*) NULL );
+            m_canvas->SetToolTip( NULL );
         }
     #endif
     }
@@ -830,28 +791,102 @@ void wxPropertyGrid::SetExtraStyle( long exStyle )
 // returns the best acceptable minimal size
 wxSize wxPropertyGrid::DoGetBestSize() const
 {
-    int hei = 15;
-    if ( m_lineHeight > hei )
-        hei = m_lineHeight;
-    wxSize sz = wxSize( 60, hei+40 );
+    int lineHeight = wxMax(15, m_lineHeight);
+
+    // don't make the grid too tall (limit height to 10 items) but don't
+    // make it too small neither
+    int numLines = wxMin
+                   (
+                    wxMax(m_pState->m_properties->GetChildCount(), 3),
+                    10
+                   );
 
+    const wxSize sz = wxSize(60, lineHeight*numLines + 40);
     CacheBestSize(sz);
     return sz;
 }
 
+// -----------------------------------------------------------------------
+
+void wxPropertyGrid::OnTLPChanging( wxWindow* newTLP )
+{
+    wxLongLong currentTime = ::wxGetLocalTimeMillis();
+
+    //
+    // Parent changed so let's redetermine and re-hook the
+    // correct top-level window.
+    if ( m_tlp )
+    {
+        m_tlp->Disconnect( wxEVT_CLOSE_WINDOW,
+                           wxCloseEventHandler(wxPropertyGrid::OnTLPClose),
+                           NULL, this );
+        m_tlpClosed = m_tlp;
+        m_tlpClosedTime = currentTime;
+    }
+
+    if ( newTLP )
+    {
+        // Only accept new tlp if same one was not just dismissed.
+        if ( newTLP != m_tlpClosed ||
+             m_tlpClosedTime+250 < currentTime )
+        {
+            newTLP->Connect( wxEVT_CLOSE_WINDOW,
+                             wxCloseEventHandler(wxPropertyGrid::OnTLPClose),
+                             NULL, this );
+            m_tlpClosed = NULL;
+        }
+        else
+        {
+            newTLP = NULL;
+        }
+    }
+
+    m_tlp = newTLP;
+}
+
+// -----------------------------------------------------------------------
+
+void wxPropertyGrid::OnTLPClose( wxCloseEvent& event )
+{
+    // ClearSelection forces value validation/commit.
+    if ( event.CanVeto() && !DoClearSelection() )
+    {
+        event.Veto();
+        return;
+    }
+
+    // Ok, it can close, set tlp pointer to NULL. Some other event
+    // handler can of course veto the close, but our OnIdle() should
+    // then be able to regain the tlp pointer.
+    OnTLPChanging(NULL);
+
+    event.Skip();
+}
+
+// -----------------------------------------------------------------------
+
+bool wxPropertyGrid::Reparent( wxWindowBase *newParent )
+{
+    OnTLPChanging((wxWindow*)newParent);
+
+    bool res = wxScrolledWindow::Reparent(newParent);
+
+    return res;
+}
+
 // -----------------------------------------------------------------------
 // wxPropertyGrid Font and Colour Methods
 // -----------------------------------------------------------------------
 
 void wxPropertyGrid::CalculateFontAndBitmapStuff( int vspacing )
 {
-       int x = 0, y = 0;
+    int x = 0, y = 0;
 
     m_captionFont = wxScrolledWindow::GetFont();
 
-       GetTextExtent(wxS("jG"), &x, &y, 0, 0, &m_captionFont);
+    GetTextExtent(wxS("jG"), &x, &y, 0, 0, &m_captionFont);
     m_subgroup_extramargin = x + (x/2);
-       m_fontHeight = y;
+    m_fontHeight = y;
 
 #if wxPG_USE_RENDERER_NATIVE
     m_iconWidth = wxPG_ICON_WIDTH;
@@ -880,7 +915,7 @@ void wxPropertyGrid::CalculateFontAndBitmapStuff( int vspacing )
         m_marginWidth = m_gutterWidth*2 + m_iconWidth;
 
     m_captionFont.SetWeight(wxBOLD);
-       GetTextExtent(wxS("jG"), &x, &y, 0, 0, &m_captionFont);
+    GetTextExtent(wxS("jG"), &x, &y, 0, 0, &m_captionFont);
 
     m_lineHeight = m_fontHeight+(2*m_spacingy)+1;
 
@@ -959,8 +994,6 @@ static int wxPGGetColAvg( const wxColour& col )
 
 void wxPropertyGrid::RegainColours()
 {
-    wxColour def_bgcol = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW );
-
     if ( !(m_coloursCustomized & 0x0002) )
     {
         wxColour col = wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE );
@@ -1038,40 +1071,16 @@ void wxPropertyGrid::ResetColours()
 bool wxPropertyGrid::SetFont( const wxFont& font )
 {
     // Must disable active editor.
-    if ( m_selected )
-    {
-        bool selRes = ClearSelection();
-        wxPG_CHECK_MSG_DBG( selRes,
-                            false,
-                            wxT("failed to deselect a property (editor probably had invalid value)") );
-    }
+    DoClearSelection();
 
-    // TODO: Following code is disabled with wxMac because
-    //   it is reported to fail. I (JMS) cannot debug it
-    //   personally right now.
-    // CS: should be fixed now, leaving old code in just in case, TODO: REMOVE
-#if 1 // !defined(__WXMAC__)
     bool res = wxScrolledWindow::SetFont( font );
-    if ( res )
+    if ( res && GetParent()) // may not have been Create()ed yet
     {
         CalculateFontAndBitmapStuff( m_vspacing );
-
-        if ( m_pState )
-            m_pState->CalculateFontAndBitmapStuff(m_vspacing);
-
         Refresh();
     }
 
     return res;
-#else
-    // ** wxMAC Only **
-    // TODO: Remove after SetFont crash fixed.
-    if ( m_iFlags & wxPG_FL_INITIALIZED )
-    {
-        wxLogDebug(wxT("WARNING: propGrid.cpp: wxPropertyGrid::SetFont has been disabled on wxMac since there has been crash reported in it. If you are willing to debug the cause, replace line '#if !defined(__WXMAC__)' with line '#if 1' in wxPropertyGrid::SetFont."));
-    }
-    return false;
-#endif
 }
 
 // -----------------------------------------------------------------------
@@ -1187,29 +1196,11 @@ void wxPropertyGrid::PrepareAfterItemsAdded()
     m_pState->m_itemsAdded = 0;
 
     if ( m_windowStyle & wxPG_AUTO_SORT )
-        Sort();
+        Sort(wxPG_SORT_TOP_LEVEL_ONLY);
 
     RecalculateVirtualSize();
 }
 
-// -----------------------------------------------------------------------
-// wxPropertyGrid property value setting and getting
-// -----------------------------------------------------------------------
-
-void wxPropertyGrid::DoSetPropertyValueUnspecified( wxPGProperty* p )
-{
-    m_pState->DoSetPropertyValueUnspecified(p);
-    DrawItemAndChildren(p);
-
-    wxPGProperty* parent = p->GetParent();
-    while ( parent &&
-            (parent->GetFlags() & wxPG_PROP_PARENTAL_FLAGS) == wxPG_PROP_MISC_PARENT )
-    {
-        DrawItem(parent);
-        parent = parent->GetParent();
-    }
-}
-
 // -----------------------------------------------------------------------
 // wxPropertyGrid property operations
 // -----------------------------------------------------------------------
@@ -1330,7 +1321,7 @@ wxString& wxPropertyGrid::ExpandEscapeSequences( wxString& dst_str, wxString& sr
 
     dst_str.clear();
 
-    for ( ; i != src_str.end(); i++ )
+    for ( ; i != src_str.end(); ++i )
     {
         wxUniChar a = *i;
 
@@ -1388,7 +1379,7 @@ wxString& wxPropertyGrid::CreateEscapeSequences( wxString& dst_str, wxString& sr
 
     dst_str.clear();
 
-    for ( ; i != src_str.end(); i++ )
+    for ( ; i != src_str.end(); ++i )
     {
         wxChar a = *i;
 
@@ -1429,7 +1420,7 @@ wxPGProperty* wxPropertyGrid::DoGetItemAtY( int y ) const
 {
     // Outside?
     if ( y < 0 )
-        return (wxPGProperty*) NULL;
+        return NULL;
 
     unsigned int a = 0;
     return m_pState->m_properties->GetItemAtY(y, m_lineHeight, &a);
@@ -1581,7 +1572,7 @@ void wxPropertyGrid::DrawItems( wxDC& dc,
         if ( dcPtr )
         {
             dc.SetClippingRegion( *clipRect );
-            paintFinishY = DoDrawItems( *dcPtr, NULL, NULL, clipRect, isBuffered );
+            paintFinishY = DoDrawItems( *dcPtr, clipRect, isBuffered );
         }
 
     #if wxPG_DOUBLE_BUFFER
@@ -1607,30 +1598,17 @@ void wxPropertyGrid::DrawItems( wxDC& dc,
 // -----------------------------------------------------------------------
 
 int wxPropertyGrid::DoDrawItems( wxDC& dc,
-                                 const wxPGProperty* firstItem,
-                                 const wxPGProperty* lastItem,
                                  const wxRect* clipRect,
                                  bool isBuffered ) const
 {
-    // TODO: This should somehow be eliminated.
-    wxRect tempClipRect;
-    if ( !clipRect )
-    {
-        wxASSERT(firstItem);
-        wxASSERT(lastItem);
-        tempClipRect = GetPropertyRect(firstItem, lastItem);
-        clipRect = &tempClipRect;
-    }
+    const wxPGProperty* firstItem;
+    const wxPGProperty* lastItem;
 
-    if ( !firstItem )
-        firstItem = DoGetItemAtY(clipRect->y);
+    firstItem = DoGetItemAtY(clipRect->y);
+    lastItem = DoGetItemAtY(clipRect->y+clipRect->height-1);
 
     if ( !lastItem )
-    {
-        lastItem = DoGetItemAtY(clipRect->y+clipRect->height-1);
-        if ( !lastItem )
-            lastItem = GetLastItem( wxPG_ITERATE_VISIBLE );
-    }
+        lastItem = GetLastItem( wxPG_ITERATE_VISIBLE );
 
     if ( m_frozen || m_height < 1 || firstItem == NULL )
         return clipRect->y;
@@ -1689,13 +1667,10 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc,
 
         //
         // clipRect conversion
-        if ( clipRect )
-        {
-            cr2 = *clipRect;
-            cr2.x -= xRelMod;
-            cr2.y -= yRelMod;
-            clipRect = &cr2;
-        }
+        cr2 = *clipRect;
+        cr2.x -= xRelMod;
+        cr2.y -= yRelMod;
+        clipRect = &cr2;
         firstItemTopY -= yRelMod;
         lastItemBottomY -= yRelMod;
     }
@@ -1705,9 +1680,9 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc,
 
     int x = m_marginWidth - xRelMod;
 
-    const wxFont& normalfont = m_font;
+    wxFont normalFont = GetFont();
 
-    bool reallyFocused = (m_iFlags & wxPG_FL_FOCUSED) ? true : false;
+    bool reallyFocused = (m_iFlags & wxPG_FL_FOCUSED) != 0;
 
     bool isEnabled = IsEnabled();
 
@@ -1742,7 +1717,7 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc,
 
     // TODO: Only render columns that are within clipping region.
 
-    dc.SetFont(normalfont);
+    dc.SetFont(normalFont);
 
     wxPropertyGridConstIterator it( state, wxPG_ITERATE_VISIBLE, firstItem );
     int endScanBottomY = lastItemBottomY + lh;
@@ -1845,10 +1820,10 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc,
         }
         else
         {
-             renderFlags |= wxPGCellRenderer::Selected;
+            renderFlags |= wxPGCellRenderer::Selected;
 
-             if ( !p->IsCategory() )
-             {
+            if ( !p->IsCategory() )
+            {
                 renderFlags |= wxPGCellRenderer::DontUseCellFgCol |
                                wxPGCellRenderer::DontUseCellBgCol;
 
@@ -1942,7 +1917,8 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc,
 
             unsigned int ci;
             int cellX = x + 1;
-            int nextCellWidth = state->m_colWidths[0];
+            int nextCellWidth = state->m_colWidths[0] -
+                                (greyDepthX - m_marginWidth);
             wxRect cellRect(greyDepthX+1, y, 0, rowHeight-1);
             int textXAdd = textMarginHere - greyDepthX;
 
@@ -2017,7 +1993,7 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc,
         }
 
         if ( fontChanged )
-            dc.SetFont(normalfont);
+            dc.SetFont(normalFont);
 
         y += rowHeight;
     }
@@ -2045,7 +2021,7 @@ wxRect wxPropertyGrid::GetPropertyRect( const wxPGProperty* p1, const wxPGProper
 
     if ( m_width < 10 || m_height < 10 ||
          !m_pState->m_properties->GetChildCount() ||
-         p1 == (wxPGProperty*) NULL )
+         p1 == NULL )
         return wxRect(0,0,0,0);
 
     int vy = 0;
@@ -2141,11 +2117,9 @@ void wxPropertyGrid::DrawItemAndChildren( wxPGProperty* p )
     if ( m_pState->m_itemsAdded || m_frozen )
         return;
 
-    wxWindow* wndPrimary = GetEditorControl();
-
     // Update child control.
     if ( m_selected && m_selected->GetParent() == p )
-        m_selected->UpdateControl(wndPrimary);
+        RefreshEditor();
 
     const wxPGProperty* lastDrawn = p->GetLastVisibleSubItem();
 
@@ -2177,13 +2151,6 @@ void wxPropertyGrid::Refresh( bool WXUNUSED(eraseBackground),
 
 void wxPropertyGrid::Clear()
 {
-    if ( m_selected )
-    {
-        bool selRes = DoSelectProperty(NULL, wxPG_SEL_DELETING);  // This must be before state clear
-        wxPG_CHECK_RET_DBG( selRes,
-                            wxT("failed to deselect a property (editor probably had invalid value)") );
-    }
-
     m_pState->DoClear();
 
     m_propHover = NULL;
@@ -2201,8 +2168,7 @@ void wxPropertyGrid::Clear()
 
 bool wxPropertyGrid::EnableCategories( bool enable )
 {
-    if ( !ClearSelection() )
-        return false;
+    DoClearSelection();
 
     if ( enable )
     {
@@ -2254,13 +2220,7 @@ void wxPropertyGrid::SwitchState( wxPropertyGridPageState* pNewState )
 
     wxPGProperty* oldSelection = m_selected;
 
-    // Deselect
-    if ( m_selected )
-    {
-        bool selRes = ClearSelection();
-        wxPG_CHECK_RET_DBG( selRes,
-                            wxT("failed to deselect a property (editor probably had invalid value)") );
-    }
+    DoClearSelection();
 
     m_pState->m_selected = oldSelection;
 
@@ -2290,7 +2250,7 @@ void wxPropertyGrid::SwitchState( wxPropertyGridPageState* pNewState )
         pNewState->OnClientWidthChange( pgWidth, pgWidth - pNewState->m_width );
     }
 
-    m_propHover = (wxPGProperty*) NULL;
+    m_propHover = NULL;
 
     // If necessary, convert state to correct mode.
     if ( orig_mode != new_state_mode )
@@ -2301,8 +2261,7 @@ void wxPropertyGrid::SwitchState( wxPropertyGridPageState* pNewState )
     else if ( !m_frozen )
     {
         // Refresh, if not frozen.
-        if ( m_pState->m_itemsAdded )
-            PrepareAfterItemsAdded();
+        m_pState->PrepareAfterItemsAdded();
 
         // Reselect
         if ( m_pState->m_selected )
@@ -2317,26 +2276,6 @@ void wxPropertyGrid::SwitchState( wxPropertyGridPageState* pNewState )
 
 // -----------------------------------------------------------------------
 
-void wxPropertyGrid::SortChildren( wxPGPropArg id )
-{
-    wxPG_PROP_ARG_CALL_PROLOG()
-
-    m_pState->SortChildren( p );
-}
-
-// -----------------------------------------------------------------------
-
-void wxPropertyGrid::Sort()
-{
-    bool selRes = ClearSelection();  // This must be before state clear
-    wxPG_CHECK_RET_DBG( selRes,
-                        wxT("failed to deselect a property (editor probably had invalid value)") );
-
-    m_pState->Sort();
-}
-
-// -----------------------------------------------------------------------
-
 // Call to SetSplitterPosition will always disable splitter auto-centering
 // if parent window is shown.
 void wxPropertyGrid::DoSetSplitterPosition_( int newxpos, bool refresh, int splitterIndex, bool allPages )
@@ -2413,7 +2352,7 @@ bool wxPropertyGrid::CommitChangesFromEditor( wxUint32 flags )
 
     // Don't do this if already processing editor event. It might
     // induce recursive dialogs and crap like that.
-    if ( m_iFlags & wxPG_FL_IN_ONCUSTOMEDITOREVENT )
+    if ( m_iFlags & wxPG_FL_IN_HANDLECUSTOMEDITOREVENT )
     {
         if ( m_inDoPropertyChanged )
             return true;
@@ -2660,11 +2599,34 @@ void wxPropertyGrid::DoShowPropertyError( wxPGProperty* WXUNUSED(property), cons
     }
 #endif
 
-    ::wxMessageBox(msg, _T("Property Error"));
+    ::wxMessageBox(msg, wxT("Property Error"));
 }
 
 // -----------------------------------------------------------------------
 
+bool wxPropertyGrid::OnValidationFailure( wxPGProperty* property,
+                                          wxVariant& invalidValue )
+{
+    wxWindow* editor = GetEditorControl();
+
+    // First call property's handler
+    property->OnValidationFailure(invalidValue);
+
+    bool res = DoOnValidationFailure(property, invalidValue);
+
+    //
+    // For non-wxTextCtrl editors, we do need to revert the value
+    if ( !editor->IsKindOf(CLASSINFO(wxTextCtrl)) &&
+         property == m_selected )
+    {
+        property->GetEditorClass()->UpdateControl(property, editor);
+    }
+
+    property->SetFlag(wxPG_PROP_INVALID_VALUE);
+
+    return res;
+}
+
 bool wxPropertyGrid::DoOnValidationFailure( wxPGProperty* property, wxVariant& WXUNUSED(invalidValue) )
 {
     int vfb = m_validationInfo.m_failureBehavior;
@@ -2712,7 +2674,7 @@ bool wxPropertyGrid::DoOnValidationFailure( wxPGProperty* property, wxVariant& W
         wxString msg = m_validationInfo.m_failureMessage;
 
         if ( !msg.length() )
-            msg = _T("You have entered invalid value. Press ESC to cancel editing.");
+            msg = wxT("You have entered invalid value. Press ESC to cancel editing.");
 
         DoShowPropertyError(property, msg);
     }
@@ -2815,8 +2777,7 @@ bool wxPropertyGrid::DoPropertyChanged( wxPGProperty* p, unsigned int selFlags )
     // control.
     if ( selFlags & wxPG_SEL_DIALOGVAL )
     {
-        if ( editor )
-            p->GetEditorClass()->UpdateControl(p, editor);
+        RefreshEditor();
     }
     else
     {
@@ -2904,27 +2865,7 @@ bool wxPropertyGrid::DoEditorValidate()
 
 // -----------------------------------------------------------------------
 
-bool wxPropertyGrid::ProcessEvent(wxEvent& event)
-{
-    wxWindow* wnd = (wxWindow*) event.GetEventObject();
-    if ( wnd && wnd->IsKindOf(CLASSINFO(wxWindow)) )
-    {
-        wxWindow* parent = wnd->GetParent();
-
-        if ( parent &&
-             (parent == m_canvas ||
-              parent->GetParent() == m_canvas) )
-        {
-            OnCustomEditorEvent(event);
-            return true;
-        }
-    }
-    return wxPanel::ProcessEvent(event);
-}
-
-// -----------------------------------------------------------------------
-
-void wxPropertyGrid::OnCustomEditorEvent( wxEvent &event )
+void wxPropertyGrid::HandleCustomEditorEvent( wxEvent &event )
 {
     wxPGProperty* selected = m_selected;
 
@@ -2933,15 +2874,15 @@ void wxPropertyGrid::OnCustomEditorEvent( wxEvent &event )
     if ( !selected )
         return;
 
-    if ( m_iFlags & wxPG_FL_IN_ONCUSTOMEDITOREVENT )
+    if ( m_iFlags & wxPG_FL_IN_HANDLECUSTOMEDITOREVENT )
         return;
 
     wxVariant pendingValue(selected->GetValueRef());
     wxWindow* wnd = GetEditorControl();
+    wxWindow* editorWnd = wxDynamicCast(event.GetEventObject(), wxWindow);
     int selFlags = 0;
     bool wasUnspecified = selected->IsValueUnspecified();
     int usesAutoUnspecified = selected->UsesAutoUnspecified();
-
     bool valueIsPending = false;
 
     m_chgInfo_changedProperty = NULL;
@@ -2963,7 +2904,7 @@ void wxPropertyGrid::OnCustomEditorEvent( wxEvent &event )
         m_prevTcValue = newTcValue;
     }
 
-    SetInternalFlag(wxPG_FL_IN_ONCUSTOMEDITOREVENT);
+    SetInternalFlag(wxPG_FL_IN_HANDLECUSTOMEDITOREVENT);
 
     bool validationFailure = false;
     bool buttonWasHandled = false;
@@ -2987,17 +2928,19 @@ void wxPropertyGrid::OnCustomEditorEvent( wxEvent &event )
 
     if ( !buttonWasHandled )
     {
-        if ( wnd )
+        if ( wnd || m_wndEditor2 )
         {
             // First call editor class' event handler.
             const wxPGEditor* editor = selected->GetEditorClass();
 
-            if ( editor->OnEvent( this, selected, wnd, event ) )
+            if ( editor->OnEvent( this, selected, editorWnd, event ) )
             {
                 // If changes, validate them
                 if ( DoEditorValidate() )
                 {
-                    if ( editor->GetValueFromControl( pendingValue, m_selected, wnd ) )
+                    if ( editor->GetValueFromControl( pendingValue,
+                                                      m_selected,
+                                                      wnd ) )
                         valueIsPending = true;
                 }
                 else
@@ -3010,7 +2953,7 @@ void wxPropertyGrid::OnCustomEditorEvent( wxEvent &event )
         // Then the property's custom handler (must be always called, unless
         // validation failed).
         if ( !validationFailure )
-            buttonWasHandled = selected->OnEvent( this, wnd, event );
+            buttonWasHandled = selected->OnEvent( this, editorWnd, event );
     }
 
     // SetValueInEvent(), as called in one of the functions referred above
@@ -3063,7 +3006,7 @@ void wxPropertyGrid::OnCustomEditorEvent( wxEvent &event )
         }
     }
 
-    ClearInternalFlag(wxPG_FL_IN_ONCUSTOMEDITOREVENT);
+    ClearInternalFlag(wxPG_FL_IN_HANDLECUSTOMEDITOREVENT);
 }
 
 // -----------------------------------------------------------------------
@@ -3074,24 +3017,25 @@ wxRect wxPropertyGrid::GetEditorWidgetRect( wxPGProperty* p, int column ) const
 {
     int itemy = p->GetY2(m_lineHeight);
     int vy = 0;
-    int cust_img_space = 0;
     int splitterX = m_pState->DoGetSplitterPosition(column-1);
     int colEnd = splitterX + m_pState->m_colWidths[column];
+    int imageOffset = 0;
 
     // TODO: If custom image detection changes from current, change this.
-    if ( m_iFlags & wxPG_FL_CUR_USES_CUSTOM_IMAGE /*p->m_flags & wxPG_PROP_CUSTOMIMAGE*/ )
+    if ( m_iFlags & wxPG_FL_CUR_USES_CUSTOM_IMAGE )
     {
         //m_iFlags |= wxPG_FL_CUR_USES_CUSTOM_IMAGE;
-        int imwid = p->OnMeasureImage().x;
-        if ( imwid < 1 ) imwid = wxPG_CUSTOM_IMAGE_WIDTH;
-        cust_img_space = imwid + wxCC_CUSTOM_IMAGE_MARGIN1 + wxCC_CUSTOM_IMAGE_MARGIN2;
+        int iw = p->OnMeasureImage().x;
+        if ( iw < 1 )
+            iw = wxPG_CUSTOM_IMAGE_WIDTH;
+        imageOffset = p->GetImageOffset(iw);
     }
 
     return wxRect
       (
-        splitterX+cust_img_space+wxPG_XBEFOREWIDGET+wxPG_CONTROL_MARGIN+1,
+        splitterX+imageOffset+wxPG_XBEFOREWIDGET+wxPG_CONTROL_MARGIN+1,
         itemy-vy,
-        colEnd-splitterX-wxPG_XBEFOREWIDGET-wxPG_CONTROL_MARGIN-cust_img_space-1,
+        colEnd-splitterX-wxPG_XBEFOREWIDGET-wxPG_CONTROL_MARGIN-imageOffset-1,
         m_lineHeight-1
       );
 }
@@ -3188,9 +3132,37 @@ void wxPropertyGrid::CustomSetCursor( int type, bool override )
 }
 
 // -----------------------------------------------------------------------
-// wxPropertyGrid property selection
+// wxPropertyGrid property selection, editor creation
 // -----------------------------------------------------------------------
 
+//
+// This class forwards events from property editor controls to wxPropertyGrid.
+class wxPropertyGridEditorEventForwarder : public wxEvtHandler
+{
+public:
+    wxPropertyGridEditorEventForwarder( wxPropertyGrid* propGrid )
+        : wxEvtHandler(), m_propGrid(propGrid)
+    {
+    }
+
+    virtual ~wxPropertyGridEditorEventForwarder()
+    {
+    }
+
+private:
+    bool ProcessEvent( wxEvent& event )
+    {
+        // Always skip
+        event.Skip();
+
+        m_propGrid->HandleCustomEditorEvent(event);
+
+        return wxEvtHandler::ProcessEvent(event);
+    }
+
+    wxPropertyGrid*         m_propGrid;
+};
+
 // Setups event handling for child control
 void wxPropertyGrid::SetupChildEventHandling( wxWindow* argWnd )
 {
@@ -3218,6 +3190,10 @@ void wxPropertyGrid::SetupChildEventHandling( wxWindow* argWnd )
             NULL, this);
     }
 
+    wxPropertyGridEditorEventForwarder* forwarder;
+    forwarder = new wxPropertyGridEditorEventForwarder(this);
+    argWnd->PushEventHandler(forwarder);
+
     argWnd->Connect(id, wxEVT_KEY_DOWN,
         wxCharEventHandler(wxPropertyGrid::OnChildKeyDown),
         NULL, this);
@@ -3247,16 +3223,20 @@ void wxPropertyGrid::FreeEditors()
     // Do not free editors immediately if processing events
     if ( m_wndEditor2 )
     {
+        wxEvtHandler* handler = m_wndEditor2->PopEventHandler(false);
         m_wndEditor2->Hide();
+        wxPendingDelete.Append( handler );
         wxPendingDelete.Append( m_wndEditor2 );
-        m_wndEditor2 = (wxWindow*) NULL;
+        m_wndEditor2 = NULL;
     }
 
     if ( m_wndEditor )
     {
+        wxEvtHandler* handler = m_wndEditor->PopEventHandler(false);
         m_wndEditor->Hide();
+        wxPendingDelete.Append( handler );
         wxPendingDelete.Append( m_wndEditor );
-        m_wndEditor = (wxWindow*) NULL;
+        m_wndEditor = NULL;
     }
 }
 
@@ -3265,10 +3245,14 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags )
 {
     /*
     if (p)
+    {
         wxLogDebug(wxT("SelectProperty( %s (%s[%i]) )"),p->m_label.c_str(),
             p->m_parent->m_label.c_str(),p->GetIndexInParent());
+    }
     else
+    {
         wxLogDebug(wxT("SelectProperty( NULL, -1 )"));
+    }
     */
 
     if ( m_inDoSelectProperty )
@@ -3310,7 +3294,7 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags )
         FreeEditors();
 
         // Prevent any further selection measures in this call
-        p = (wxPGProperty*) NULL;
+        p = NULL;
     }
     else
     {
@@ -3361,8 +3345,8 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags )
             FreeEditors();
             m_selColumn = -1;
 
-            m_selected = (wxPGProperty*) NULL;
-            m_pState->m_selected = (wxPGProperty*) NULL;
+            m_selected = NULL;
+            m_pState->m_selected = NULL;
 
             // We need to always fully refresh the grid here
             Refresh(false);
@@ -3387,10 +3371,7 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags )
             if ( p != prev )
                 m_iFlags &= ~(wxPG_FL_VALIDATION_FAILED);
 
-            wxASSERT( m_wndEditor == (wxWindow*) NULL );
-
-            // Do we need OnMeasureCalls?
-            wxSize imsz = p->OnMeasureImage();
+            wxASSERT( m_wndEditor == NULL );
 
             //
             // Only create editor for non-disabled non-caption
@@ -3589,7 +3570,7 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags )
 
     if ( !(GetExtraStyle() & wxPG_EX_HELP_AS_TOOLTIPS) )
     {
-        wxStatusBar* statusbar = (wxStatusBar*) NULL;
+        wxStatusBar* statusbar = NULL;
         if ( !(m_iFlags & wxPG_FL_NOSTATUSBARHELP) )
         {
             wxFrame* frame = wxDynamicCast(::wxGetTopLevelParent(this),wxFrame);
@@ -3627,7 +3608,8 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags )
     m_inDoSelectProperty = 0;
 
     // call wx event handler (here so that it also occurs on deselection)
-    SendEvent( wxEVT_PG_SELECTED, m_selected, NULL, flags );
+    if ( !(flags & wxPG_SEL_DONT_SEND_EVENT) )
+        SendEvent( wxEVT_PG_SELECTED, m_selected, NULL, flags );
 
     return true;
 }
@@ -3650,11 +3632,53 @@ bool wxPropertyGrid::UnfocusEditor()
 
 // -----------------------------------------------------------------------
 
-// This method is not inline because it called dozens of times
-// (i.e. two-arg function calls create smaller code size).
+void wxPropertyGrid::RefreshEditor()
+{
+    wxPGProperty* p = m_selected;
+    if ( !p ) 
+        return;
+
+    wxWindow* wnd = GetEditorControl();
+    if ( !wnd )
+        return;
+
+    // Set editor font boldness - must do this before
+    // calling UpdateControl().
+    if ( HasFlag(wxPG_BOLD_MODIFIED) )
+    {
+        if ( p->HasFlag(wxPG_PROP_MODIFIED) )
+            wnd->SetFont(GetCaptionFont());
+        else
+            wnd->SetFont(GetFont());
+    }
+
+    const wxPGEditor* editorClass = p->GetEditorClass();
+
+    editorClass->UpdateControl(p, wnd);
+
+    if ( p->IsValueUnspecified() )
+        editorClass ->SetValueToUnspecified(p, wnd);
+}
+
+// -----------------------------------------------------------------------
+
+bool wxPropertyGrid::SelectProperty( wxPGPropArg id, bool focus )
+{
+    wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
+
+    int flags = wxPG_SEL_DONT_SEND_EVENT;
+    if ( focus )
+        flags |= wxPG_SEL_FOCUS;
+
+    return DoSelectProperty(p, flags);
+}
+
+// -----------------------------------------------------------------------
+
 bool wxPropertyGrid::DoClearSelection()
 {
-    return DoSelectProperty((wxPGProperty*)NULL);
+    // Unlike ClearSelection(), here we send the wxEVT_PG_SELECTED event.
+    return DoSelectProperty(NULL, 0);
 }
 
 // -----------------------------------------------------------------------
@@ -3666,10 +3690,9 @@ bool wxPropertyGrid::DoCollapse( wxPGProperty* p, bool sendEvents )
     wxPGProperty* pwc = wxStaticCast(p, wxPGProperty);
 
     // If active editor was inside collapsed section, then disable it
-    if ( m_selected && m_selected->IsSomeParent (p) )
+    if ( m_selected && m_selected->IsSomeParent(p) )
     {
-        if ( !ClearSelection() )
-            return false;
+        DoClearSelection();
     }
 
     // Store dont-center-splitter flag 'cause we need to temporarily set it
@@ -3738,7 +3761,7 @@ bool wxPropertyGrid::DoExpand( wxPGProperty* p, bool sendEvents )
     }
 
     // Clear dont-center-splitter flag if it wasn't set
-    m_iFlags = m_iFlags & ~(wxPG_FL_DONT_CENTER_SPLITTER) | old_flag;
+    m_iFlags = (m_iFlags & ~wxPG_FL_DONT_CENTER_SPLITTER) | old_flag;
 
     return res;
 }
@@ -3754,8 +3777,7 @@ bool wxPropertyGrid::DoHideProperty( wxPGProperty* p, bool hide, int flags )
          ( m_selected == p || m_selected->IsSomeParent(p) )
        )
         {
-            if ( !ClearSelection() )
-                return false;
+            DoClearSelection();
         }
 
     m_pState->DoHideProperty(p, hide, flags);
@@ -3783,17 +3805,10 @@ void wxPropertyGrid::RecalculateVirtualSize( int forceXPos )
 
     m_pState->EnsureVirtualHeight();
 
-#ifdef __WXDEBUG__
-    int by1 = m_pState->GetVirtualHeight();
-    int by2 = m_pState->GetActualVirtualHeight();
-    if ( by1 != by2 )
-    {
-        wxString s = wxString::Format(wxT("VirtualHeight=%i, ActualVirtualHeight=%i, should match!"), by1, by2);
-        wxASSERT_MSG( false,
-                      s.c_str() );
-        wxLogDebug(s);
-    }
-#endif
+    wxASSERT_LEVEL_2_MSG(
+        m_pState->GetVirtualHeight() == m_pState->GetActualVirtualHeight(),
+        "VirtualHeight and ActualVirtualHeight should match"
+    );
 
     m_iFlags |= wxPG_FL_RECALCULATING_VIRTUAL_SIZE;
 
@@ -3804,7 +3819,7 @@ void wxPropertyGrid::RecalculateVirtualSize( int forceXPos )
     GetClientSize(&width,&height);
 
     // Now adjust virtual size.
-       SetVirtualSize(x, y);
+    SetVirtualSize(x, y);
 
     int xAmount = 0;
     int xPos = 0;
@@ -3823,7 +3838,7 @@ void wxPropertyGrid::RecalculateVirtualSize( int forceXPos )
     else if ( xPos > (xAmount-(width/wxPG_PIXELS_PER_UNIT)) )
         xPos = 0;
 
-    int yAmount = (y+wxPG_PIXELS_PER_UNIT+2)/wxPG_PIXELS_PER_UNIT;
+    int yAmount = y / wxPG_PIXELS_PER_UNIT;
     int yPos = GetScrollPos( wxVERTICAL );
 
     SetScrollbars( wxPG_PIXELS_PER_UNIT, wxPG_PIXELS_PER_UNIT,
@@ -4236,9 +4251,9 @@ bool wxPropertyGrid::HandleMouseMove( int x, unsigned int y, wxMouseEvent &event
         int curPropHoverY = y - (y % ih);
 
         // On which item it hovers
-        if ( ( !m_propHover )
+        if ( !m_propHover
              ||
-             ( m_propHover && ( sy < m_propHoverY || sy >= (m_propHoverY+ih) ) )
+             ( sy < m_propHoverY || sy >= (m_propHoverY+ih) )
            )
         {
             // Mouse moves on another property
@@ -4301,7 +4316,7 @@ bool wxPropertyGrid::HandleMouseMove( int x, unsigned int y, wxMouseEvent &event
                         if ( space )
                         {
                             int tw, th;
-                           GetTextExtent( tipString, &tw, &th, 0, 0, &m_font );
+                            GetTextExtent( tipString, &tw, &th, 0, 0 );
                             if ( tw > space )
                             {
                                 SetToolTip( tipString );
@@ -4350,8 +4365,7 @@ bool wxPropertyGrid::HandleMouseMove( int x, unsigned int y, wxMouseEvent &event
             // (also not if we were dragging and its started
             // outside the splitter region)
 
-            if ( m_propHover &&
-                 !m_propHover->IsCategory() &&
+            if ( !m_propHover->IsCategory() &&
                  !event.Dragging() )
             {
 
@@ -4464,7 +4478,7 @@ bool wxPropertyGrid::OnMouseCommon( wxMouseEvent& event, int* px, int* py )
     wxRect r;
     if ( wnd )
         r = wnd->GetRect();
-    if ( wnd == (wxWindow*) NULL || m_dragStatus ||
+    if ( wnd == NULL || m_dragStatus ||
          (
            ux <= (splitterX + wxPG_SPLITTERX_DETECTMARGIN2) ||
            ux >= (r.x+r.width) ||
@@ -4726,7 +4740,7 @@ void wxPropertyGrid::ClearActionTriggers( int action )
 {
     wxPGHashMapI2I::iterator it;
 
-    for ( it = m_actionTriggers.begin(); it != m_actionTriggers.end(); it++ )
+    for ( it = m_actionTriggers.begin(); it != m_actionTriggers.end(); ++it )
     {
         if ( it->second == action )
         {
@@ -4741,9 +4755,7 @@ void wxPropertyGrid::HandleKeyEvent( wxKeyEvent &event, bool fromChild )
     // Handles key event when editor control is not focused.
     //
 
-    wxASSERT( !m_frozen );
-    if ( m_frozen )
-        return;
+    wxCHECK2(!m_frozen, return);
 
     // Travelsal between items, collapsing/expanding, etc.
     int keycode = event.GetKeyCode();
@@ -4835,6 +4847,11 @@ void wxPropertyGrid::HandleKeyEvent( wxKeyEvent &event, bool fromChild )
     // Except for TAB and ESC, handle child control events in child control
     if ( fromChild )
     {
+        // Only propagate event if it had modifiers
+        if ( !event.HasModifiers() )
+        {
+            event.StopPropagation();
+        }
         event.Skip();
         return;
     }
@@ -4852,9 +4869,7 @@ void wxPropertyGrid::HandleKeyEvent( wxKeyEvent &event, bool fromChild )
         // Travel and expand/collapse
         int selectDir = -2;
 
-        if ( p->GetChildCount() &&
-             !(p->m_flags & wxPG_PROP_DISABLED)
-           )
+        if ( p->GetChildCount() )
         {
             if ( action == wxPG_ACTION_COLLAPSE_PROPERTY || secondAction == wxPG_ACTION_COLLAPSE_PROPERTY )
             {
@@ -4908,6 +4923,19 @@ void wxPropertyGrid::HandleKeyEvent( wxKeyEvent &event, bool fromChild )
 
 void wxPropertyGrid::OnKey( wxKeyEvent &event )
 {
+    // If there was editor open and focused, then this event should not
+    // really be processed here.
+    if ( IsEditorFocused() )
+    {
+        // However, if event had modifiers, it is probably still best
+        // to skip it.
+        if ( event.HasModifiers() )
+            event.Skip();
+        else
+            event.StopPropagation();
+        return;
+    }
+
     HandleKeyEvent(event, false);
 }
 
@@ -4952,6 +4980,14 @@ void wxPropertyGrid::OnIdle( wxIdleEvent& WXUNUSED(event) )
 
     if ( newFocused != m_curFocused )
         HandleFocusChange( newFocused );
+
+    //
+    // Check if top-level parent has changed
+    wxWindow* tlp = ::wxGetTopLevelParent(this);
+    if ( tlp != m_tlp )
+    {
+        OnTLPChanging(tlp);
+    }
 }
 
 bool wxPropertyGrid::IsEditorFocused() const
@@ -5051,11 +5087,7 @@ void wxPropertyGrid::OnFocusEvent( wxFocusEvent& event )
 void wxPropertyGrid::OnChildFocusEvent( wxChildFocusEvent& event )
 {
     HandleFocusChange((wxWindow*)event.GetEventObject());
-
-    //
-    // event.Skip() being commented out is aworkaround for bug reported
-    // in ticket #4840 (wxScrolledWindow problem with automatic scrolling).
-    //event.Skip();
+    event.Skip();
 }
 
 // -----------------------------------------------------------------------
@@ -5082,15 +5114,18 @@ void wxPropertyGrid::OnCaptureChange( wxMouseCaptureChangedEvent& WXUNUSED(event
 // -----------------------------------------------------------------------
 
 // noDefCheck = true prevents infinite recursion.
-wxPGEditor* wxPropertyGrid::RegisterEditorClass( wxPGEditor* editorClass,
-                                                 bool noDefCheck )
+wxPGEditor* wxPropertyGrid::DoRegisterEditorClass( wxPGEditor* editorClass,
+                                                   const wxString& editorName,
+                                                   bool noDefCheck )
 {
     wxASSERT( editorClass );
 
     if ( !noDefCheck && wxPGGlobalVars->m_mapEditorClasses.empty() )
         RegisterDefaultEditors();
 
-    wxString name = editorClass->GetName();
+    wxString name = editorName;
+    if ( name.length() == 0 )
+        name = editorClass->GetName();
 
     // Existing editor under this name?
     wxPGHashMapS2P::iterator vt_it = wxPGGlobalVars->m_mapEditorClasses.find(name);
@@ -5113,7 +5148,7 @@ wxPGEditor* wxPropertyGrid::RegisterEditorClass( wxPGEditor* editorClass,
 
 // Use this in RegisterDefaultEditors.
 #define wxPGRegisterDefaultEditorClass(EDITOR) \
-    if ( wxPGEditor_##EDITOR == (wxPGEditor*) NULL ) \
+    if ( wxPGEditor_##EDITOR == NULL ) \
     { \
         wxPGEditor_##EDITOR = wxPropertyGrid::RegisterEditorClass( \
             new wxPG##EDITOR##Editor, true ); \
@@ -5184,7 +5219,7 @@ bool wxPGStringTokenizer::HasMoreTokens()
                 }
                 else
                 {
-                    i++;
+                    ++i;
                     m_curPos = i;
                     return true;
                 }
@@ -5196,7 +5231,7 @@ bool wxPGStringTokenizer::HasMoreTokens()
                 prev_a = wxT('\0');
             }
         }
-        i++;
+        ++i;
     }
 
     m_curPos = str.end();
@@ -5227,7 +5262,6 @@ wxPGChoiceEntry::wxPGChoiceEntry()
 
 wxPGChoicesData::wxPGChoicesData()
 {
-    m_refCount = 1;
 }
 
 wxPGChoicesData::~wxPGChoicesData()
@@ -5272,241 +5306,6 @@ wxPGChoiceEntry& wxPGChoicesData::Insert( int index,
     return ownEntry;
 }
 
-// -----------------------------------------------------------------------
-// wxPGChoices
-// -----------------------------------------------------------------------
-
-wxPGChoiceEntry& wxPGChoices::Add( const wxString& label, int value )
-{
-    EnsureData();
-
-    wxPGChoiceEntry entry(label, value);
-    return m_data->Insert( -1, entry );
-}
-
-// -----------------------------------------------------------------------
-
-wxPGChoiceEntry& wxPGChoices::Add( const wxString& label, const wxBitmap& bitmap, int value )
-{
-    EnsureData();
-
-    wxPGChoiceEntry entry(label, value);
-    entry.SetBitmap(bitmap);
-    return m_data->Insert( -1, entry );
-}
-
-// -----------------------------------------------------------------------
-
-wxPGChoiceEntry& wxPGChoices::Insert( const wxPGChoiceEntry& entry, int index )
-{
-    EnsureData();
-    return m_data->Insert( index, entry );
-}
-
-// -----------------------------------------------------------------------
-
-wxPGChoiceEntry& wxPGChoices::Insert( const wxString& label, int index, int value )
-{
-    EnsureData();
-
-    wxPGChoiceEntry entry(label, value);
-    return m_data->Insert( index, entry );
-}
-
-// -----------------------------------------------------------------------
-
-wxPGChoiceEntry& wxPGChoices::AddAsSorted( const wxString& label, int value )
-{
-    EnsureData();
-
-    size_t index = 0;
-
-    while ( index < GetCount() )
-    {
-        int cmpRes = GetLabel(index).Cmp(label);
-        if ( cmpRes > 0 )
-            break;
-        index++;
-    }
-
-    wxPGChoiceEntry entry(label, value);
-    return m_data->Insert( index, entry );
-}
-
-// -----------------------------------------------------------------------
-
-void wxPGChoices::Add( const wxChar** labels, const ValArrItem* values )
-{
-    EnsureData();
-
-    unsigned int itemcount = 0;
-    const wxChar** p = &labels[0];
-    while ( *p ) { p++; itemcount++; }
-
-    unsigned int i;
-    for ( i = 0; i < itemcount; i++ )
-    {
-        int value = i;
-        if ( values )
-            value = values[i];
-        wxPGChoiceEntry entry(labels[i], value);
-        m_data->Insert( i, entry );
-    }
-}
-
-// -----------------------------------------------------------------------
-
-void wxPGChoices::Add( const wxArrayString& arr, const wxArrayInt& arrint )
-{
-    EnsureData();
-
-    unsigned int i;
-    unsigned int itemcount = arr.size();
-
-    for ( i = 0; i < itemcount; i++ )
-    {
-        int value = i;
-        if ( &arrint && arrint.size() )
-            value = arrint[i];
-        wxPGChoiceEntry entry(arr[i], value);
-        m_data->Insert( i, entry );
-    }
-}
-
-// -----------------------------------------------------------------------
-
-void wxPGChoices::RemoveAt(size_t nIndex, size_t count)
-{
-    wxASSERT( m_data->m_refCount != 0xFFFFFFF );
-    m_data->m_items.erase(m_data->m_items.begin()+nIndex,
-                          m_data->m_items.begin()+nIndex+count);
-}
-
-// -----------------------------------------------------------------------
-
-int wxPGChoices::Index( const wxString& str ) const
-{
-    if ( IsOk() )
-    {
-        unsigned int i;
-        for ( i=0; i< m_data->GetCount(); i++ )
-        {
-            const wxPGChoiceEntry& entry = m_data->Item(i);
-            if ( entry.HasText() && entry.GetText() == str )
-                return i;
-        }
-    }
-    return -1;
-}
-
-// -----------------------------------------------------------------------
-
-int wxPGChoices::Index( int val ) const
-{
-    if ( IsOk() )
-    {
-        unsigned int i;
-        for ( i=0; i< m_data->GetCount(); i++ )
-        {
-            const wxPGChoiceEntry& entry = m_data->Item(i);
-            if ( entry.GetValue() == val )
-                return i;
-        }
-    }
-    return -1;
-}
-
-// -----------------------------------------------------------------------
-
-wxArrayString wxPGChoices::GetLabels() const
-{
-    wxArrayString arr;
-    unsigned int i;
-
-    if ( this && IsOk() )
-        for ( i=0; i<GetCount(); i++ )
-            arr.push_back(GetLabel(i));
-
-    return arr;
-}
-
-// -----------------------------------------------------------------------
-
-wxArrayInt wxPGChoices::GetValuesForStrings( const wxArrayString& strings ) const
-{
-    wxArrayInt arr;
-
-    if ( IsOk() )
-    {
-        unsigned int i;
-        for ( i=0; i< strings.size(); i++ )
-        {
-            int index = Index(strings[i]);
-            if ( index >= 0 )
-                arr.Add(GetValue(index));
-            else
-                arr.Add(wxPG_INVALID_VALUE);
-        }
-    }
-
-    return arr;
-}
-
-// -----------------------------------------------------------------------
-
-wxArrayInt wxPGChoices::GetIndicesForStrings( const wxArrayString& strings,
-                                              wxArrayString* unmatched ) const
-{
-    wxArrayInt arr;
-
-    if ( IsOk() )
-    {
-        unsigned int i;
-        for ( i=0; i< strings.size(); i++ )
-        {
-            const wxString& str = strings[i];
-            int index = Index(str);
-            if ( index >= 0 )
-                arr.Add(index);
-            else if ( unmatched )
-                unmatched->Add(str);
-        }
-    }
-
-    return arr;
-}
-
-// -----------------------------------------------------------------------
-
-void wxPGChoices::AssignData( wxPGChoicesData* data )
-{
-    Free();
-
-    if ( data != wxPGChoicesEmptyData )
-    {
-        m_data = data;
-        data->m_refCount++;
-    }
-}
-
-// -----------------------------------------------------------------------
-
-void wxPGChoices::Init()
-{
-    m_data = wxPGChoicesEmptyData;
-}
-
-// -----------------------------------------------------------------------
-
-void wxPGChoices::Free()
-{
-    if ( m_data != wxPGChoicesEmptyData )
-    {
-        m_data->DecRef();
-        m_data = wxPGChoicesEmptyData;
-    }
-}
-
 // -----------------------------------------------------------------------
 // wxPropertyGridEvent
 // -----------------------------------------------------------------------
@@ -5514,15 +5313,15 @@ void wxPGChoices::Free()
 IMPLEMENT_DYNAMIC_CLASS(wxPropertyGridEvent, wxCommandEvent)
 
 
-DEFINE_EVENT_TYPE( wxEVT_PG_SELECTED )
-DEFINE_EVENT_TYPE( wxEVT_PG_CHANGING )
-DEFINE_EVENT_TYPE( wxEVT_PG_CHANGED )
-DEFINE_EVENT_TYPE( wxEVT_PG_HIGHLIGHTED )
-DEFINE_EVENT_TYPE( wxEVT_PG_RIGHT_CLICK )
-DEFINE_EVENT_TYPE( wxEVT_PG_PAGE_CHANGED )
-DEFINE_EVENT_TYPE( wxEVT_PG_ITEM_EXPANDED )
-DEFINE_EVENT_TYPE( wxEVT_PG_ITEM_COLLAPSED )
-DEFINE_EVENT_TYPE( wxEVT_PG_DOUBLE_CLICK )
+wxDEFINE_EVENT( wxEVT_PG_SELECTED, wxPropertyGridEvent );
+wxDEFINE_EVENT( wxEVT_PG_CHANGING, wxPropertyGridEvent );
+wxDEFINE_EVENT( wxEVT_PG_CHANGED, wxPropertyGridEvent );
+wxDEFINE_EVENT( wxEVT_PG_HIGHLIGHTED, wxPropertyGridEvent );
+wxDEFINE_EVENT( wxEVT_PG_RIGHT_CLICK, wxPropertyGridEvent );
+wxDEFINE_EVENT( wxEVT_PG_PAGE_CHANGED, wxPropertyGridEvent );
+wxDEFINE_EVENT( wxEVT_PG_ITEM_EXPANDED, wxPropertyGridEvent );
+wxDEFINE_EVENT( wxEVT_PG_ITEM_COLLAPSED, wxPropertyGridEvent );
+wxDEFINE_EVENT( wxEVT_PG_DOUBLE_CLICK, wxPropertyGridEvent );
 
 
 // -----------------------------------------------------------------------
@@ -5707,7 +5506,7 @@ wxPGChoices wxPropertyGridPopulator::ParseChoices( const wxString& choicesString
             int state = 0;
             bool labelValid = false;
 
-            for ( ; it != choicesString.end(); it++ )
+            for ( ; it != choicesString.end(); ++it )
             {
                 wxChar c = *it;