]> git.saurik.com Git - wxWidgets.git/blobdiff - src/propgrid/propgrid.cpp
fixing setting initial value under osx_cocoa for single line text controls
[wxWidgets.git] / src / propgrid / propgrid.cpp
index ad2faab46f8b12fd9ed5631b55f5471662fbc2d0..18370b90df7aa76163f3c6f7fc1db799e731aa8b 100644 (file)
@@ -4,7 +4,7 @@
 // Author:      Jaakko Salli
 // Modified by:
 // Created:     2004-09-25
-// RCS-ID:      $Id:
+// RCS-ID:      $Id$
 // Copyright:   (c) Jaakko Salli
 // Licence:     wxWindows license
 /////////////////////////////////////////////////////////////////////////////
 // This define is necessary to prevent macro clearing
 #define __wxPG_SOURCE_FILE__
 
-#include <wx/propgrid/propgrid.h>
-#include <wx/propgrid/editors.h>
+#include "wx/propgrid/propgrid.h"
+#include "wx/propgrid/editors.h"
 
 #if wxPG_USE_RENDERER_NATIVE
-    #include <wx/renderer.h>
+    #include "wx/renderer.h"
 #endif
 
-#include <wx/odcombo.h>
+#include "wx/odcombo.h"
 
 #include "wx/timer.h"
 #include "wx/dcbuffer.h"
-#include <wx/clipbrd.h>
-#include <wx/dataobj.h>
-
-#ifdef __WXMSW__
-    #include <wx/msw/private.h>
-#endif
 
 // Two pics for the expand / collapse buttons.
 // Files are not supplied with this project (since it is
 
 
 //#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
 
 // -----------------------------------------------------------------------
 
@@ -134,13 +128,13 @@ void wxPropertyGrid::AutoGetTranslation ( bool ) { }
 
 // -----------------------------------------------------------------------
 
-const wxChar *wxPropertyGridNameStr = wxT("wxPropertyGrid");
+const char wxPropertyGridNameStr[] = "wxPropertyGrid";
 
 // -----------------------------------------------------------------------
 // Statics in one class for easy destruction.
 // -----------------------------------------------------------------------
 
-#include <wx/module.h>
+#include "wx/module.h"
 
 class wxPGGlobalVarsClassManager : public wxModule
 {
@@ -154,7 +148,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 +167,7 @@ wxPGGlobalVarsClass::wxPGGlobalVarsClass()
     m_boolChoices.Add(_("False"));
     m_boolChoices.Add(_("True"));
 
-    m_fontFamilyChoices = (wxPGChoices*) NULL;
+    m_fontFamilyChoices = NULL;
 
     m_defaultRenderer = new wxPGDefaultRenderer();
 
@@ -176,7 +179,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 +191,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,130 +233,6 @@ void wxPropertyGridInitGlobalsIfNeeded()
 {
 }
 
-// -----------------------------------------------------------------------
-// wxPGBrush
-// -----------------------------------------------------------------------
-
-//
-// This class is a wxBrush derivative used in the background colour
-// brush cache. It adds wxPG-type colour-in-long to the class.
-// JMS: Yes I know wxBrush doesn't actually hold the value (refcounted
-//   object does), but this is simpler implementation and equally
-//   effective.
-//
-
-class wxPGBrush : public wxBrush
-{
-public:
-    wxPGBrush( const wxColour& colour );
-    wxPGBrush();
-    virtual ~wxPGBrush() { }
-    void SetColour2( const wxColour& colour );
-    inline long GetColourAsLong() const { return m_colAsLong; }
-private:
-    long    m_colAsLong;
-};
-
-
-void wxPGBrush::SetColour2( const wxColour& colour )
-{
-    wxBrush::SetColour(colour);
-    m_colAsLong = wxPG_COLOUR(colour.Red(),colour.Green(),colour.Blue());
-}
-
-
-wxPGBrush::wxPGBrush() : wxBrush()
-{
-    m_colAsLong = 0;
-}
-
-
-wxPGBrush::wxPGBrush( const wxColour& colour ) : wxBrush(colour)
-{
-    m_colAsLong = wxPG_COLOUR(colour.Red(),colour.Green(),colour.Blue());
-}
-
-
-// -----------------------------------------------------------------------
-// wxPGColour
-// -----------------------------------------------------------------------
-
-//
-// Same as wxPGBrush, but for wxColour instead.
-//
-
-class wxPGColour : public wxColour
-{
-public:
-    wxPGColour( const wxColour& colour );
-    wxPGColour();
-    virtual ~wxPGColour() { }
-    void SetColour2( const wxColour& colour );
-    inline long GetColourAsLong() const { return m_colAsLong; }
-private:
-    long    m_colAsLong;
-};
-
-
-void wxPGColour::SetColour2( const wxColour& colour )
-{
-    *this = colour;
-    m_colAsLong = wxPG_COLOUR(colour.Red(),colour.Green(),colour.Blue());
-}
-
-
-wxPGColour::wxPGColour() : wxColour()
-{
-    m_colAsLong = 0;
-}
-
-
-wxPGColour::wxPGColour( const wxColour& colour ) : wxColour(colour)
-{
-    m_colAsLong = wxPG_COLOUR(colour.Red(),colour.Green(),colour.Blue());
-}
-
-
-// -----------------------------------------------------------------------
-// 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
 // -----------------------------------------------------------------------
@@ -408,24 +286,12 @@ protected:
         pg->OnKey( event );
     }
 
-    void OnKeyUp( wxKeyEvent& event )
-    {
-        wxPropertyGrid* pg = wxStaticCast(GetParent(), wxPropertyGrid);
-        pg->OnKeyUp( event );
-    }
-
-    void OnNavigationKey( wxNavigationKeyEvent& event )
-    {
-        wxPropertyGrid* pg = wxStaticCast(GetParent(), wxPropertyGrid);
-        pg->OnNavigationKey( event );
-    }
-
     void OnPaint( wxPaintEvent& event );
-    
+
     // Always be focussable, even with child windows
     virtual void SetCanFocus(bool WXUNUSED(canFocus))
     {  wxPanel::SetCanFocus(true); }
-    
+
 
 private:
     DECLARE_EVENT_TABLE()
@@ -443,9 +309,6 @@ BEGIN_EVENT_TABLE(wxPGCanvas, wxPanel)
     EVT_RIGHT_UP(wxPGCanvas::OnMouseRightClick)
     EVT_LEFT_DCLICK(wxPGCanvas::OnMouseDoubleClick)
     EVT_KEY_DOWN(wxPGCanvas::OnKey)
-    EVT_KEY_UP(wxPGCanvas::OnKeyUp)
-    EVT_CHAR(wxPGCanvas::OnKey)
-    EVT_NAVIGATION_KEY(wxPGCanvas::OnNavigationKey)
 END_EVENT_TABLE()
 
 
@@ -463,6 +326,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 );
 
@@ -508,7 +377,7 @@ wxPropertyGrid::wxPropertyGrid( wxWindow *parent,
                                 const wxPoint& pos,
                                 const wxSize& size,
                                 long style,
-                                const wxChar* name )
+                                const wxString& name )
     : wxScrolledWindow()
 {
     Init1();
@@ -522,26 +391,19 @@ bool wxPropertyGrid::Create( wxWindow *parent,
                              const wxPoint& pos,
                              const wxSize& size,
                              long style,
-                             const wxChar* name )
+                             const wxString& name )
 {
 
-    if ( !(style&wxBORDER_MASK) )
-        style |= wxSIMPLE_BORDER;
+    if (!(style&wxBORDER_MASK))
+    {
+        style |= wxBORDER_THEME;
+    }
 
     style |= wxVSCROLL;
 
-#ifdef __WXMSW__
-    // This prevents crash under Win2K, but still
-    // enables keyboard navigation
-    if ( style & wxTAB_TRAVERSAL )
-    {
-        style &= ~(wxTAB_TRAVERSAL);
-        style |= wxWANTS_CHARS;
-    }
-#else
-    if ( style & wxTAB_TRAVERSAL )
-        style |= wxWANTS_CHARS;
-#endif
+    // Filter out wxTAB_TRAVERSAL - we will handle TABs manually
+    style &= ~(wxTAB_TRAVERSAL);
+    style |= wxWANTS_CHARS;
 
     wxScrolledWindow::Create(parent,id,pos,size,style,name);
 
@@ -562,14 +424,17 @@ void wxPropertyGrid::Init1()
         wxPropertyGrid::RegisterDefaultEditors();
 
     m_iFlags = 0;
-    m_pState = (wxPropertyGridPageState*) NULL;
-    m_wndEditor = m_wndEditor2 = (wxWindow*) NULL;
-    m_selected = (wxPGProperty*) NULL;
-    m_selColumn = -1;
-    m_propHover = (wxPGProperty*) NULL;
+    m_pState = NULL;
+    m_wndEditor = m_wndEditor2 = NULL;
+    m_selColumn = 1;
+    m_colHover = 1;
+    m_propHover = NULL;
+    m_labelEditor = NULL;
+    m_labelEditorProperty = NULL;
     m_eventObject = this;
-    m_curFocused = (wxWindow*) NULL;
-    m_tlwHandler = NULL;
+    m_curFocused = NULL;
+    m_processedEvent = NULL;
+    m_sortFunction = NULL;
     m_inDoPropertyChanged = 0;
     m_inCommitChangesFromEditor = 0;
     m_inDoSelectProperty = 0;
@@ -586,12 +451,8 @@ void wxPropertyGrid::Init1()
     AddActionTrigger( wxPG_ACTION_EXPAND_PROPERTY, WXK_RIGHT);
     AddActionTrigger( wxPG_ACTION_COLLAPSE_PROPERTY, WXK_LEFT);
     AddActionTrigger( wxPG_ACTION_CANCEL_EDIT, WXK_ESCAPE );
-    AddActionTrigger( wxPG_ACTION_CUT, 'X', wxMOD_CONTROL );
-    AddActionTrigger( wxPG_ACTION_CUT, WXK_DELETE, wxMOD_SHIFT );
-    AddActionTrigger( wxPG_ACTION_COPY, 'C', wxMOD_CONTROL);
-    AddActionTrigger( wxPG_ACTION_COPY, WXK_INSERT, wxMOD_CONTROL );
-    AddActionTrigger( wxPG_ACTION_PASTE, 'V', wxMOD_CONTROL );
-    AddActionTrigger( wxPG_ACTION_PASTE, WXK_INSERT, wxMOD_SHIFT );
+    AddActionTrigger( wxPG_ACTION_PRESS_BUTTON, WXK_DOWN, wxMOD_ALT );
+    AddActionTrigger( wxPG_ACTION_PRESS_BUTTON, WXK_F4 );
 
     m_coloursCustomized = 0;
     m_frozen = 0;
@@ -599,14 +460,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
@@ -620,10 +481,6 @@ void wxPropertyGrid::Init1()
 
     m_width = m_height = 0;
 
-    SetButtonShortcut(0);
-
-    m_keyComboConsumed = 0;
-
     m_commonValues.push_back(new wxPGCommonValue(_("Unspecified"), wxPGGlobalVars->m_defaultRenderer) );
     m_cvUnspecified = 0;
 
@@ -642,7 +499,7 @@ void wxPropertyGrid::Init2()
 #ifdef __WXMAC__
    // Smaller controls on Mac
    SetWindowVariant(wxWINDOW_VARIANT_SMALL);
-#endif 
+#endif
 
     // Now create state, if one didn't exist already
     // (wxPropertyGridManager might have created it for us).
@@ -667,57 +524,46 @@ 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 );
-
-    // Add base brush item
-    m_arrBgBrushes.Add((void*)new wxPGBrush());
+    CalculateFontAndBitmapStuff( wxPG_DEFAULT_VSPACING );
 
-    // Add base colour items
-    m_arrFgCols.Add((void*)new wxPGColour());
-    m_arrFgCols.Add((void*)new wxPGColour());
+    // Allocate cell datas indirectly by calling setter
+    m_propertyDefaultCell.SetBgCol(*wxBLACK);
+    m_categoryDefaultCell.SetBgCol(*wxBLACK);
 
     RegainColours();
 
     // 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;
 
-       // 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();
 
     m_canvas = new wxPGCanvas();
-    m_canvas->Create(this, 1, wxPoint(0, 0), GetClientSize(),
-                     (GetWindowStyle() & wxTAB_TRAVERSAL) | wxWANTS_CHARS | wxCLIP_CHILDREN);
+    m_canvas->Create(this, wxID_ANY, wxPoint(0, 0), GetClientSize(),
+                     wxWANTS_CHARS | wxCLIP_CHILDREN);
     m_canvas->SetBackgroundStyle( wxBG_STYLE_CUSTOM );
 
     m_iFlags |= wxPG_FL_INITIALIZED;
@@ -736,7 +582,38 @@ wxPropertyGrid::~wxPropertyGrid()
 {
     size_t i;
 
-    DoSelectProperty(NULL);
+#if wxUSE_THREADS
+    wxCriticalSectionLocker(wxPGGlobalVars->m_critSect);
+#endif
+
+    //
+    // Remove grid and property pointers from live wxPropertyGridEvents.
+    for ( i=0; i<m_liveEvents.size(); i++ )
+    {
+        wxPropertyGridEvent* evt = m_liveEvents[i];
+        evt->SetPropertyGrid(NULL);
+        evt->SetProperty(NULL);
+    }
+    m_liveEvents.clear();
+
+    if ( m_processedEvent )
+    {
+        // All right... we are being deleted while wxPropertyGrid event
+        // is being sent. Make sure that event propagates as little
+        // as possible (although usually this is not enough to prevent
+        // a crash).
+        m_processedEvent->Skip(false);
+        m_processedEvent->StopPropagation();
+
+        // Let's use wxMessageBox to make the message appear more
+        // reliably (and *before* the crash can happen).
+        ::wxMessageBox("wxPropertyGrid was being destroyed in an event "
+                       "generated by it. This usually leads to a crash "
+                       "so it is recommended to destroy the control "
+                       "at idle time instead.");
+    }
+
+    DoSelectProperty(NULL, wxPG_SEL_NOVALIDATE|wxPG_SEL_DONT_SEND_EVENT);
 
     // This should do prevent things from going too badly wrong
     m_iFlags &= ~(wxPG_FL_INITIALIZED);
@@ -744,49 +621,39 @@ 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
+    if ( GetExtraStyle() & wxPG_EX_ENABLE_TLP_TRACKING )
+    {
+        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 ")
+                      wxS("lost!!! (if you don't want this to happen, ")
+                      wxS("close your frames and dialogs using ")
+                      wxS("Close(false).)") );
+    }
 
 #if wxPG_DOUBLE_BUFFER
     if ( m_doubleBuffer )
         delete m_doubleBuffer;
 #endif
 
-    //m_selected = (wxPGProperty*) NULL;
-
     if ( m_iFlags & wxPG_FL_CREATEDSTATE )
         delete m_pState;
 
     delete m_cursorSizeWE;
 
 #ifndef wxPG_ICON_WIDTH
-       delete m_expandbmp;
-       delete m_collbmp;
+    delete m_expandbmp;
+    delete m_collbmp;
 #endif
 
-    // Delete cached text colours.
-    for ( i=0; i<m_arrFgCols.size(); i++ )
-    {
-        delete (wxPGColour*)m_arrFgCols.Item(i);
-    }
-
-    // Delete cached brushes.
-    for ( i=0; i<m_arrBgBrushes.size(); i++ )
-    {
-        delete (wxPGBrush*)m_arrBgBrushes.Item(i);
-    }
-
     // Delete common value records
     for ( i=0; i<m_commonValues.size(); i++ )
     {
-        delete GetCommonValue(i);
+        // Use temporary variable to work around possible strange VC6 (asserts because m_size is zero)
+        wxPGCommonValue* value = m_commonValues[i];
+        delete value;
     }
 }
 
@@ -856,7 +723,7 @@ void wxPropertyGrid::SetWindowStyleFlag( long style )
             //
             // Tooltips disabled
             //
-            m_canvas->SetToolTip( (wxToolTip*) NULL );
+            m_canvas->SetToolTip( NULL );
         }
     #endif
     }
@@ -899,151 +766,585 @@ void wxPropertyGrid::Thaw()
     #endif
 
         // Force property re-selection
-        if ( m_selected )
-            DoSelectProperty(m_selected, wxPG_SEL_FORCE);
+        // NB: We must copy the selection.
+        wxArrayPGProperty selection = m_pState->m_selection;
+        DoSetSelection(selection, wxPG_SEL_FORCE);
     }
 }
 
 // -----------------------------------------------------------------------
 
-void wxPropertyGrid::SetExtraStyle( long exStyle )
+bool wxPropertyGrid::DoAddToSelection( wxPGProperty* prop, int selFlags )
 {
-    if ( exStyle & wxPG_EX_NATIVE_DOUBLE_BUFFERING )
-    {
-#if defined(__WXMSW__)
-
-        /*
-        // Don't use WS_EX_COMPOSITED just now.
-        HWND hWnd;
+    wxCHECK( prop, false );
 
-        if ( m_iFlags & wxPG_FL_IN_MANAGER )
-            hWnd = (HWND)GetParent()->GetHWND();
-        else
-            hWnd = (HWND)GetHWND();
+    if ( !(GetExtraStyle() & wxPG_EX_MULTIPLE_SELECTION) )
+        return DoSelectProperty(prop, selFlags);
 
-        ::SetWindowLong( hWnd, GWL_EXSTYLE,
-                         ::GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_COMPOSITED );
-        */
+    wxArrayPGProperty& selection = m_pState->m_selection;
 
-//#elif defined(__WXGTK20__)
-#endif
-        // Only apply wxPG_EX_NATIVE_DOUBLE_BUFFERING if the window
-        // truly was double-buffered.
-        if ( !this->IsDoubleBuffered() )
-        {
-            exStyle &= ~(wxPG_EX_NATIVE_DOUBLE_BUFFERING);
-        }
-        else
-        {
-        #if wxPG_DOUBLE_BUFFER
-            delete m_doubleBuffer;
-            m_doubleBuffer = NULL;
-        #endif
-        }
+    if ( !selection.size() )
+    {
+        return DoSelectProperty(prop, selFlags);
     }
+    else
+    {
+        // For categories, only one can be selected at a time
+        if ( prop->IsCategory() || selection[0]->IsCategory() )
+            return true;
 
-    wxScrolledWindow::SetExtraStyle( exStyle );
+        selection.push_back(prop);
 
-    if ( exStyle & wxPG_EX_INIT_NOCAT )
-        m_pState->InitNonCatMode();
+        if ( !(selFlags & wxPG_SEL_DONT_SEND_EVENT) )
+        {
+            SendEvent( wxEVT_PG_SELECTED, prop, NULL );
+        }
 
-    if ( exStyle & wxPG_EX_HELP_AS_TOOLTIPS )
-        m_windowStyle |= wxPG_TOOLTIPS;
+        DrawItem(prop);
+    }
 
-    // Set global style
-    wxPGGlobalVars->m_extraStyle = exStyle;
+    return true;
 }
 
 // -----------------------------------------------------------------------
 
-// returns the best acceptable minimal size
-wxSize wxPropertyGrid::DoGetBestSize() const
+bool wxPropertyGrid::DoRemoveFromSelection( wxPGProperty* prop, int selFlags )
 {
-    int hei = 15;
-    if ( m_lineHeight > hei )
-        hei = m_lineHeight;
-    wxSize sz = wxSize( 60, hei+40 );
+    wxCHECK( prop, false );
+    bool res;
 
-    CacheBestSize(sz);
-    return sz;
+    wxArrayPGProperty& selection = m_pState->m_selection;
+    if ( selection.size() <= 1 )
+    {
+        res = DoSelectProperty(NULL, selFlags);
+    }
+    else
+    {
+        m_pState->DoRemoveFromSelection(prop);
+        DrawItem(prop);
+        res = true;
+    }
+
+    return res;
 }
 
-// -----------------------------------------------------------------------
-// wxPropertyGrid Font and Colour Methods
 // -----------------------------------------------------------------------
 
-void wxPropertyGrid::CalculateFontAndBitmapStuff( int vspacing )
+bool wxPropertyGrid::DoSelectAndEdit( wxPGProperty* prop,
+                                      unsigned int colIndex,
+                                      unsigned int selFlags )
 {
-       int x = 0, y = 0;
-
-    m_captionFont = wxScrolledWindow::GetFont();
-
-       GetTextExtent(wxS("jG"), &x, &y, 0, 0, &m_captionFont);
-    m_subgroup_extramargin = x + (x/2);
-       m_fontHeight = y;
-
-#if wxPG_USE_RENDERER_NATIVE
-    m_iconWidth = wxPG_ICON_WIDTH;
-#elif wxPG_ICON_WIDTH
-    // scale icon
-    m_iconWidth = (m_fontHeight * wxPG_ICON_WIDTH) / 13;
-    if ( m_iconWidth < 5 ) m_iconWidth = 5;
-    else if ( !(m_iconWidth & 0x01) ) m_iconWidth++; // must be odd
-
-#endif
-
-    m_gutterWidth = m_iconWidth / wxPG_GUTTER_DIV;
-    if ( m_gutterWidth < wxPG_GUTTER_MIN )
-        m_gutterWidth = wxPG_GUTTER_MIN;
-
-    int vdiv = 6;
-    if ( vspacing <= 1 ) vdiv = 12;
-    else if ( vspacing >= 3 ) vdiv = 3;
-
-    m_spacingy = m_fontHeight / vdiv;
-    if ( m_spacingy < wxPG_YSPACING_MIN )
-        m_spacingy = wxPG_YSPACING_MIN;
-
-    m_marginWidth = 0;
-    if ( !(m_windowStyle & wxPG_HIDE_MARGIN) )
-        m_marginWidth = m_gutterWidth*2 + m_iconWidth;
-
-    m_captionFont.SetWeight(wxBOLD);
-       GetTextExtent(wxS("jG"), &x, &y, 0, 0, &m_captionFont);
+    //
+    // NB: Enable following if label editor background colour is
+    //     ever changed to any other than m_colSelBack.
+    //
+    // We use this workaround to prevent visible flicker when editing
+    // a cell. Atleast on wxMSW, there is a difficult to find
+    // (and perhaps prevent) redraw somewhere between making property
+    // selected and enabling label editing.
+    //
+    //wxColour prevColSelBack = m_colSelBack;
+    //m_colSelBack = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW );
 
-    m_lineHeight = m_fontHeight+(2*m_spacingy)+1;
+    bool res;
 
-    // button spacing
-    m_buttonSpacingY = (m_lineHeight - m_iconHeight) / 2;
-    if ( m_buttonSpacingY < 0 ) m_buttonSpacingY = 0;
+    if ( colIndex == 1 )
+    {
+        res = DoSelectProperty(prop, selFlags);
+    }
+    else
+    {
+        // send event
+        DoClearSelection(false, wxPG_SEL_NO_REFRESH);
 
-    if ( m_pState )
-        m_pState->CalculateFontAndBitmapStuff(vspacing);
+        if ( m_pState->m_editableColumns.Index(colIndex) == wxNOT_FOUND )
+        {
+            res = DoAddToSelection(prop, selFlags);
+        }
+        else
+        {
+            res = DoAddToSelection(prop, selFlags|wxPG_SEL_NO_REFRESH);
 
-    if ( m_iFlags & wxPG_FL_INITIALIZED )
-        RecalculateVirtualSize();
+            DoBeginLabelEdit(colIndex, selFlags);
+        }
+    }
 
-    InvalidateBestSize();
+    //m_colSelBack = prevColSelBack;
+    return res;
 }
 
 // -----------------------------------------------------------------------
 
-void wxPropertyGrid::OnSysColourChanged( wxSysColourChangedEvent &WXUNUSED(event) )
+bool wxPropertyGrid::AddToSelectionFromInputEvent( wxPGProperty* prop,
+                                                   unsigned int colIndex,
+                                                   wxMouseEvent* mouseEvent,
+                                                   int selFlags )
 {
-    RegainColours();
-    Refresh();
-}
-
-// -----------------------------------------------------------------------
+    bool alreadySelected = m_pState->DoIsPropertySelected(prop);
+    bool res = true;
+    bool addToExistingSelection;
 
-static wxColour wxPGAdjustColour(const wxColour& src, int ra,
-                                 int ga = 1000, int ba = 1000,
-                                 bool forceDifferent = false)
-{
-    if ( ga >= 1000 )
-        ga = ra;
-    if ( ba >= 1000 )
-        ba = ra;
+    if ( GetExtraStyle() & wxPG_EX_MULTIPLE_SELECTION )
+    {
+        if ( mouseEvent )
+        {
+            if ( mouseEvent->GetEventType() == wxEVT_RIGHT_DOWN ||
+                 mouseEvent->GetEventType() == wxEVT_RIGHT_UP )
+            {
+                // Allow right-click for context menu without
+                // disturbing the selection.
+                if ( GetSelectedProperties().size() <= 1 ||
+                     !alreadySelected )
+                    return DoSelectAndEdit(prop, colIndex, selFlags);
+                return true;
+            }
+            else
+            {
+                addToExistingSelection = mouseEvent->ShiftDown();
+            }
+        }
+        else
+        {
+            addToExistingSelection = false;
+        }
+    }
+    else
+    {
+        addToExistingSelection = false;
+    }
+
+    if ( addToExistingSelection )
+    {
+        if ( !alreadySelected )
+        {
+            res = DoAddToSelection(prop, selFlags);
+        }
+        else if ( GetSelectedProperties().size() > 1 )
+        {
+            res = DoRemoveFromSelection(prop, selFlags);
+        }
+    }
+    else
+    {
+        res = DoSelectAndEdit(prop, colIndex, selFlags);
+    }
+
+    return res;
+}
+
+// -----------------------------------------------------------------------
+
+void wxPropertyGrid::DoSetSelection( const wxArrayPGProperty& newSelection,
+                                     int selFlags )
+{
+    if ( newSelection.size() > 0 )
+    {
+        if ( !DoSelectProperty(newSelection[0], selFlags) )
+            return;
+    }
+    else
+    {
+        DoClearSelection(false, selFlags);
+    }
+
+    for ( unsigned int i = 1; i < newSelection.size(); i++ )
+    {
+        DoAddToSelection(newSelection[i], selFlags);
+    }
+
+    Refresh();
+}
+
+// -----------------------------------------------------------------------
+
+void wxPropertyGrid::MakeColumnEditable( unsigned int column,
+                                         bool editable )
+{
+    wxASSERT( column != 1 );
+
+    wxArrayInt& cols = m_pState->m_editableColumns;
+
+    if ( editable )
+    {
+        cols.push_back(column);
+    }
+    else
+    {
+        for ( int i = cols.size() - 1; i > 0; i-- )
+        {
+            if ( cols[i] == (int)column )
+                cols.erase( cols.begin() + i );
+        }
+    }
+}
+
+// -----------------------------------------------------------------------
+
+void wxPropertyGrid::DoBeginLabelEdit( unsigned int colIndex,
+                                       int selFlags )
+{
+    wxPGProperty* selected = GetSelection();
+    wxCHECK_RET(selected, wxT("No property selected"));
+    wxCHECK_RET(colIndex != 1, wxT("Do not use this for column 1"));
+
+    if ( !(selFlags & wxPG_SEL_DONT_SEND_EVENT) )
+    {
+        if ( SendEvent( wxEVT_PG_LABEL_EDIT_BEGIN,
+                        selected, NULL, 0,
+                        colIndex ) )
+            return;
+    }
+
+    wxString text;
+    const wxPGCell* cell = NULL;
+    if ( selected->HasCell(colIndex) )
+    {
+        cell = &selected->GetCell(colIndex);
+        if ( !cell->HasText() && colIndex == 0 )
+            text = selected->GetLabel();
+    }
+
+    if ( !cell  )
+    {
+        if ( colIndex == 0 )
+            text = selected->GetLabel();
+        else
+            cell = &selected->GetOrCreateCell(colIndex);
+    }
+
+    if ( cell && cell->HasText() )
+        text = cell->GetText();
+
+    DoEndLabelEdit(true, wxPG_SEL_NOVALIDATE);  // send event
+
+    m_selColumn = colIndex;
+
+    wxRect r = GetEditorWidgetRect(selected, m_selColumn);
+
+    wxWindow* tc = GenerateEditorTextCtrl(r.GetPosition(),
+                                          r.GetSize(),
+                                          text,
+                                          NULL,
+                                          wxTE_PROCESS_ENTER,
+                                          0,
+                                          colIndex);
+
+    wxWindowID id = tc->GetId();
+    tc->Connect(id, wxEVT_COMMAND_TEXT_ENTER,
+        wxCommandEventHandler(wxPropertyGrid::OnLabelEditorEnterPress),
+        NULL, this);
+    tc->Connect(id, wxEVT_KEY_DOWN,
+        wxKeyEventHandler(wxPropertyGrid::OnLabelEditorKeyPress),
+        NULL, this);
+
+    tc->SetFocus();
+
+    m_labelEditor = wxStaticCast(tc, wxTextCtrl);
+    m_labelEditorProperty = selected;
+}
+
+// -----------------------------------------------------------------------
+
+void
+wxPropertyGrid::OnLabelEditorEnterPress( wxCommandEvent& WXUNUSED(event) )
+{
+    DoEndLabelEdit(true);
+}
+
+// -----------------------------------------------------------------------
+
+void wxPropertyGrid::OnLabelEditorKeyPress( wxKeyEvent& event )
+{
+    int keycode = event.GetKeyCode();
+
+    if ( keycode == WXK_ESCAPE )
+    {
+        DoEndLabelEdit(false);
+    }
+    else
+    {
+        event.Skip();
+    }
+}
+
+// -----------------------------------------------------------------------
+
+void wxPropertyGrid::DoEndLabelEdit( bool commit, int selFlags )
+{
+    if ( !m_labelEditor )
+        return;
+
+    wxPGProperty* prop = m_labelEditorProperty;
+    wxASSERT(prop);
+
+    if ( commit )
+    {
+        if ( !(selFlags & wxPG_SEL_DONT_SEND_EVENT) )
+        {
+            // wxPG_SEL_NOVALIDATE is passed correctly in selFlags
+            if ( SendEvent( wxEVT_PG_LABEL_EDIT_ENDING,
+                            prop, NULL, selFlags,
+                            m_selColumn ) )
+                return;
+        }
+
+        wxString text = m_labelEditor->GetValue();
+        wxPGCell* cell = NULL;
+        if ( prop->HasCell(m_selColumn) )
+        {
+            cell = &prop->GetCell(m_selColumn);
+        }
+        else
+        {
+            if ( m_selColumn == 0 )
+                prop->SetLabel(text);
+            else
+                cell = &prop->GetOrCreateCell(m_selColumn);
+        }
+
+        if ( cell )
+            cell->SetText(text);
+    }
+
+    m_selColumn = 1;
+
+    DestroyEditorWnd(m_labelEditor);
+    m_labelEditor = NULL;
+    m_labelEditorProperty = NULL;
+
+    DrawItem(prop);
+}
+
+// -----------------------------------------------------------------------
+
+void wxPropertyGrid::SetExtraStyle( long exStyle )
+{
+    if ( exStyle & wxPG_EX_ENABLE_TLP_TRACKING )
+        OnTLPChanging(::wxGetTopLevelParent(this));
+    else
+        OnTLPChanging(NULL);
+
+    if ( exStyle & wxPG_EX_NATIVE_DOUBLE_BUFFERING )
+    {
+#if defined(__WXMSW__)
+
+        /*
+        // Don't use WS_EX_COMPOSITED just now.
+        HWND hWnd;
+
+        if ( m_iFlags & wxPG_FL_IN_MANAGER )
+            hWnd = (HWND)GetParent()->GetHWND();
+        else
+            hWnd = (HWND)GetHWND();
+
+        ::SetWindowLong( hWnd, GWL_EXSTYLE,
+                         ::GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_COMPOSITED );
+        */
+
+//#elif defined(__WXGTK20__)
+#endif
+        // Only apply wxPG_EX_NATIVE_DOUBLE_BUFFERING if the window
+        // truly was double-buffered.
+        if ( !this->IsDoubleBuffered() )
+        {
+            exStyle &= ~(wxPG_EX_NATIVE_DOUBLE_BUFFERING);
+        }
+        else
+        {
+        #if wxPG_DOUBLE_BUFFER
+            delete m_doubleBuffer;
+            m_doubleBuffer = NULL;
+        #endif
+        }
+    }
+
+    wxScrolledWindow::SetExtraStyle( exStyle );
+
+    if ( exStyle & wxPG_EX_INIT_NOCAT )
+        m_pState->InitNonCatMode();
+
+    if ( exStyle & wxPG_EX_HELP_AS_TOOLTIPS )
+        m_windowStyle |= wxPG_TOOLTIPS;
+
+    // Set global style
+    wxPGGlobalVars->m_extraStyle = exStyle;
+}
+
+// -----------------------------------------------------------------------
+
+// returns the best acceptable minimal size
+wxSize wxPropertyGrid::DoGetBestSize() const
+{
+    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
+                   );
+
+    wxClientDC dc(const_cast<wxPropertyGrid *>(this));
+    int width = m_marginWidth;
+    for ( unsigned int i = 0; i < m_pState->m_colWidths.size(); i++ )
+    {
+        width += m_pState->GetColumnFitWidth(dc, m_pState->DoGetRoot(), i, true);
+    }
+
+    const wxSize sz = wxSize(width, lineHeight*numLines + 40);
+
+    CacheBestSize(sz);
+    return sz;
+}
+
+// -----------------------------------------------------------------------
+
+void wxPropertyGrid::OnTLPChanging( wxWindow* newTLP )
+{
+    if ( newTLP == m_tlp )
+        return;
+
+    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;
+
+    m_captionFont = wxScrolledWindow::GetFont();
+
+    GetTextExtent(wxS("jG"), &x, &y, 0, 0, &m_captionFont);
+    m_subgroup_extramargin = x + (x/2);
+    m_fontHeight = y;
+
+#if wxPG_USE_RENDERER_NATIVE
+    m_iconWidth = wxPG_ICON_WIDTH;
+#elif wxPG_ICON_WIDTH
+    // scale icon
+    m_iconWidth = (m_fontHeight * wxPG_ICON_WIDTH) / 13;
+    if ( m_iconWidth < 5 ) m_iconWidth = 5;
+    else if ( !(m_iconWidth & 0x01) ) m_iconWidth++; // must be odd
+
+#endif
+
+    m_gutterWidth = m_iconWidth / wxPG_GUTTER_DIV;
+    if ( m_gutterWidth < wxPG_GUTTER_MIN )
+        m_gutterWidth = wxPG_GUTTER_MIN;
+
+    int vdiv = 6;
+    if ( vspacing <= 1 ) vdiv = 12;
+    else if ( vspacing >= 3 ) vdiv = 3;
+
+    m_spacingy = m_fontHeight / vdiv;
+    if ( m_spacingy < wxPG_YSPACING_MIN )
+        m_spacingy = wxPG_YSPACING_MIN;
+
+    m_marginWidth = 0;
+    if ( !(m_windowStyle & wxPG_HIDE_MARGIN) )
+        m_marginWidth = m_gutterWidth*2 + m_iconWidth;
+
+    m_captionFont.SetWeight(wxBOLD);
+    GetTextExtent(wxS("jG"), &x, &y, 0, 0, &m_captionFont);
+
+    m_lineHeight = m_fontHeight+(2*m_spacingy)+1;
+
+    // button spacing
+    m_buttonSpacingY = (m_lineHeight - m_iconHeight) / 2;
+    if ( m_buttonSpacingY < 0 ) m_buttonSpacingY = 0;
+
+    if ( m_pState )
+        m_pState->CalculateFontAndBitmapStuff(vspacing);
+
+    if ( m_iFlags & wxPG_FL_INITIALIZED )
+        RecalculateVirtualSize();
+
+    InvalidateBestSize();
+}
+
+// -----------------------------------------------------------------------
+
+void wxPropertyGrid::OnSysColourChanged( wxSysColourChangedEvent &WXUNUSED(event) )
+{
+    RegainColours();
+    Refresh();
+}
+
+// -----------------------------------------------------------------------
+
+static wxColour wxPGAdjustColour(const wxColour& src, int ra,
+                                 int ga = 1000, int ba = 1000,
+                                 bool forceDifferent = false)
+{
+    if ( ga >= 1000 )
+        ga = ra;
+    if ( ba >= 1000 )
+        ba = ra;
 
     // Recursion guard (allow 2 max)
     static int isinside = 0;
@@ -1088,8 +1389,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 );
@@ -1104,6 +1403,7 @@ void wxPropertyGrid::RegainColours()
             m_colCapBack = wxPGAdjustColour(col,-colDec);
         else
             m_colCapBack = col;
+        m_categoryDefaultCell.GetData()->SetBgCol(m_colCapBack);
     }
 
     if ( !(m_coloursCustomized & 0x0001) )
@@ -1118,27 +1418,21 @@ void wxPropertyGrid::RegainColours()
     #endif
         wxColour capForeCol = wxPGAdjustColour(m_colCapBack,colDec,5000,5000,true);
         m_colCapFore = capForeCol;
-
-        // Set the cached colour as well.
-        ((wxPGColour*)m_arrFgCols.Item(1))->SetColour2(capForeCol);
+        m_categoryDefaultCell.GetData()->SetFgCol(capForeCol);
     }
 
     if ( !(m_coloursCustomized & 0x0008) )
     {
         wxColour bgCol = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW );
         m_colPropBack = bgCol;
-
-        // Set the cached brush as well.
-        ((wxPGBrush*)m_arrBgBrushes.Item(0))->SetColour2(bgCol);
+        m_propertyDefaultCell.GetData()->SetBgCol(bgCol);
     }
 
     if ( !(m_coloursCustomized & 0x0010) )
     {
         wxColour fgCol = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT );
         m_colPropFore = fgCol;
-
-        // Set the cached colour as well.
-        ((wxPGColour*)m_arrFgCols.Item(0))->SetColour2(fgCol);
+        m_propertyDefaultCell.GetData()->SetFgCol(fgCol);
     }
 
     if ( !(m_coloursCustomized & 0x0020) )
@@ -1172,39 +1466,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.
-#if !defined(__WXMAC__)
     bool res = wxScrolledWindow::SetFont( font );
-    if ( res )
+    if ( res && GetParent()) // may not have been Create()ed yet if SetFont called from SetWindowVariant
     {
         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
 }
 
 // -----------------------------------------------------------------------
@@ -1232,8 +1503,7 @@ void wxPropertyGrid::SetCellBackgroundColour( const wxColour& col )
     m_colPropBack = col;
     m_coloursCustomized |= 0x08;
 
-    // Set the cached brush as well.
-    ((wxPGBrush*)m_arrBgBrushes.Item(0))->SetColour2(col);
+    m_propertyDefaultCell.GetData()->SetBgCol(col);
 
     Refresh();
 }
@@ -1245,8 +1515,7 @@ void wxPropertyGrid::SetCellTextColour( const wxColour& col )
     m_colPropFore = col;
     m_coloursCustomized |= 0x10;
 
-    // Set the cached colour as well.
-    ((wxPGColour*)m_arrFgCols.Item(0))->SetColour2(col);
+    m_propertyDefaultCell.GetData()->SetFgCol(col);
 
     Refresh();
 }
@@ -1282,180 +1551,33 @@ void wxPropertyGrid::SetSelectionBackgroundColour( const wxColour& col )
 
 void wxPropertyGrid::SetSelectionTextColour( const wxColour& col )
 {
-    m_colSelFore = col;
-    m_coloursCustomized |= 0x40;
-    Refresh();
-}
-
-// -----------------------------------------------------------------------
-
-void wxPropertyGrid::SetCaptionBackgroundColour( const wxColour& col )
-{
-    m_colCapBack = col;
-    m_coloursCustomized |= 0x02;
-    Refresh();
-}
-
-// -----------------------------------------------------------------------
-
-void wxPropertyGrid::SetCaptionTextColour( const wxColour& col )
-{
-    m_colCapFore = col;
-    m_coloursCustomized |= 0x04;
-
-    // Set the cached colour as well.
-    ((wxPGColour*)m_arrFgCols.Item(1))->SetColour2(col);
-
-    Refresh();
-}
-
-// -----------------------------------------------------------------------
-
-void wxPropertyGrid::SetBackgroundColourIndex( wxPGProperty* p, int index )
-{
-    unsigned char ind = index;
-
-    p->m_bgColIndex = ind;
-
-    unsigned int i;
-    for ( i=0; i<p->GetChildCount(); i++ )
-        SetBackgroundColourIndex(p->Item(i),index);
-}
-
-// -----------------------------------------------------------------------
-
-void wxPropertyGrid::SetPropertyBackgroundColour( wxPGPropArg id, const wxColour& colour )
-{
-    wxPG_PROP_ARG_CALL_PROLOG()
-
-    size_t i;
-    int colInd = -1;
-
-    long colAsLong = wxPG_COLOUR(colour.Red(),colour.Green(),colour.Blue());
-
-    // As it is most likely that the previous colour is used, start comparison
-    // from the end.
-    for ( i=(m_arrBgBrushes.size()-1); i>0; i-- )
-    {
-        if ( ((wxPGBrush*)m_arrBgBrushes.Item(i))->GetColourAsLong() == colAsLong )
-        {
-            colInd = i;
-            break;
-        }
-    }
-
-    if ( colInd < 0 )
-    {
-        colInd = m_arrBgBrushes.size();
-        wxCHECK_RET( colInd < 256, wxT("wxPropertyGrid: Warning - Only 255 different property background colours allowed.") );
-        m_arrBgBrushes.Add( (void*)new wxPGBrush(colour) );
-    }
-
-    // Set indexes
-    SetBackgroundColourIndex(p,colInd);
-
-    // If this was on a visible grid, then draw it.
-    DrawItemAndChildren(p);
-}
-
-// -----------------------------------------------------------------------
-
-wxColour wxPropertyGrid::GetPropertyBackgroundColour( wxPGPropArg id ) const
-{
-    wxPG_PROP_ARG_CALL_PROLOG_RETVAL(wxColour())
-
-    return ((wxPGBrush*)m_arrBgBrushes.Item(p->m_bgColIndex))->GetColour();
-}
-
-// -----------------------------------------------------------------------
-
-void wxPropertyGrid::SetTextColourIndex( wxPGProperty* p, int index, int flags )
-{
-    unsigned char ind = index;
-
-    p->m_fgColIndex = ind;
-
-    if ( p->GetChildCount() && (flags & wxPG_RECURSE) )
-    {
-        unsigned int i;
-        for ( i=0; i<p->GetChildCount(); i++ )
-            SetTextColourIndex( p->Item(i), index, flags );
-    }
-}
-
-// -----------------------------------------------------------------------
-
-int wxPropertyGrid::CacheColour( const wxColour& colour )
-{
-    unsigned int i;
-    int colInd = -1;
-
-    long colAsLong = wxPG_COLOUR(colour.Red(),colour.Green(),colour.Blue());
-
-    // As it is most likely that the previous colour is used, start comparison
-    // from the end.
-    for ( i=(m_arrFgCols.size()-1); i>0; i-- )
-    {
-        if ( ((wxPGColour*)m_arrFgCols.Item(i))->GetColourAsLong() == colAsLong )
-        {
-            colInd = i;
-            break;
-        }
-    }
-
-    if ( colInd < 0 )
-    {
-        colInd = m_arrFgCols.size();
-        wxCHECK_MSG( colInd < 256, 0, wxT("wxPropertyGrid: Warning - Only 255 different property foreground colours allowed.") );
-        m_arrFgCols.Add( (void*)new wxPGColour(colour) );
-    }
-
-    return colInd;
-}
-
-// -----------------------------------------------------------------------
-
-void wxPropertyGrid::SetPropertyTextColour( wxPGPropArg id, const wxColour& colour,
-                                            bool recursively )
-{
-    wxPG_PROP_ARG_CALL_PROLOG()
-
-    if ( p->IsCategory() )
-    {
-        wxPropertyCategory* cat = (wxPropertyCategory*) p;
-        cat->SetTextColIndex(CacheColour(colour));
-    }
-
-    // Set indexes
-    int flags = 0;
-    if ( recursively )
-        flags |= wxPG_RECURSE;
-    SetTextColourIndex(p, CacheColour(colour), flags);
-
-    DrawItemAndChildren(p);
+    m_colSelFore = col;
+    m_coloursCustomized |= 0x40;
+    Refresh();
 }
 
 // -----------------------------------------------------------------------
 
-wxColour wxPropertyGrid::GetPropertyTextColour( wxPGPropArg id ) const
+void wxPropertyGrid::SetCaptionBackgroundColour( const wxColour& col )
 {
-    wxPG_PROP_ARG_CALL_PROLOG_RETVAL(wxColour())
+    m_colCapBack = col;
+    m_coloursCustomized |= 0x02;
 
-    return wxColour(*((wxPGColour*)m_arrFgCols.Item(p->m_fgColIndex)));
+    m_categoryDefaultCell.GetData()->SetBgCol(col);
+
+    Refresh();
 }
 
-void wxPropertyGrid::SetPropertyColoursToDefault( wxPGPropArg id )
+// -----------------------------------------------------------------------
+
+void wxPropertyGrid::SetCaptionTextColour( const wxColour& col )
 {
-    wxPG_PROP_ARG_CALL_PROLOG()
+    m_colCapFore = col;
+    m_coloursCustomized |= 0x04;
 
-    SetBackgroundColourIndex( p, 0 );
-    SetTextColourIndex( p, 0, wxPG_RECURSE );
+    m_categoryDefaultCell.GetData()->SetFgCol(col);
 
-    if ( p->IsCategory() )
-    {
-        wxPropertyCategory* cat = (wxPropertyCategory*) p;
-        cat->SetTextColIndex(1);
-    }
+    Refresh();
 }
 
 // -----------------------------------------------------------------------
@@ -1469,28 +1591,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->GetFlags() & wxPG_PROP_PARENTAL_FLAGS) == wxPG_PROP_MISC_PARENT )
-    {
-        DrawItem(parent);
-        parent = parent->GetParent();
-    }
-}
-
 // -----------------------------------------------------------------------
 // wxPropertyGrid property operations
 // -----------------------------------------------------------------------
@@ -1611,7 +1716,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;
 
@@ -1669,7 +1774,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;
 
@@ -1710,7 +1815,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);
@@ -1862,7 +1967,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
@@ -1888,30 +1993,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;
@@ -1970,13 +2062,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;
     }
@@ -1986,11 +2075,11 @@ 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();
+    bool isPgEnabled = IsEnabled();
 
     //
     // Prepare some pens and brushes that are often changed to.
@@ -2001,6 +2090,12 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc,
     wxBrush capbgbrush(m_colCapBack,wxSOLID);
     wxPen linepen(m_colLine,1,wxSOLID);
 
+    wxColour selBackCol;
+    if ( isPgEnabled )
+        selBackCol = m_colSelBack;
+    else
+        selBackCol = m_colMargin;
+
     // pen that has same colour as text
     wxPen outlinepen(m_colPropFore,1,wxSOLID);
 
@@ -2014,7 +2109,7 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc,
         dc.DrawRectangle(-1-xRelMod,firstItemTopY-1,x+2,lastItemBottomY-firstItemTopY+2);
     }
 
-    const wxPGProperty* selected = m_selected;
+    const wxPGProperty* firstSelected = GetSelection();
     const wxPropertyGridPageState* state = m_pState;
 
 #if wxPG_REFRESH_CONTROLS_AFTER_REPAINT
@@ -2023,7 +2118,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;
@@ -2065,7 +2160,7 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc,
 
         int rowHeight = m_fontHeight+(m_spacingy*2)+1;
         int textMarginHere = x;
-        int renderFlags = wxPGCellRenderer::Control;
+        int renderFlags = 0;
 
         int greyDepth = m_marginWidth;
         if ( !(windowStyle & wxPG_HIDE_CATEGORIES) )
@@ -2088,8 +2183,28 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc,
 
         int y2 = y + lh;
 
+#ifdef __WXMSW__
         // Margin Edge
-        dc.DrawLine( greyDepthX, y, greyDepthX, y2 );
+        // Modified by JACS to not draw a margin if wxPG_HIDE_MARGIN is specified, since it
+        // looks better, at least under Windows when we have a themed border (the themed-window-specific
+        // whitespace between the real border and the propgrid margin exacerbates the double-border look).
+
+        // Is this or its parent themed?
+        bool suppressMarginEdge = (GetWindowStyle() & wxPG_HIDE_MARGIN) &&
+            (((GetWindowStyle() & wxBORDER_MASK) == wxBORDER_THEME) ||
+            (((GetWindowStyle() & wxBORDER_MASK) == wxBORDER_NONE) && ((GetParent()->GetWindowStyle() & wxBORDER_MASK) == wxBORDER_THEME)));
+#else
+        bool suppressMarginEdge = false;
+#endif
+        if (!suppressMarginEdge)
+            dc.DrawLine( greyDepthX, y, greyDepthX, y2 );
+        else
+        {
+            // Blank out the margin edge
+            dc.SetPen(wxPen(GetBackgroundColour()));
+            dc.DrawLine( greyDepthX, y, greyDepthX, y2 );
+            dc.SetPen( linepen );
+        }
 
         // Splitters
         unsigned int si;
@@ -2109,58 +2224,85 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc,
 
         dc.DrawLine( greyDepthX, y2-1, gridWidth-xRelMod, y2-1 );
 
-        if ( p == selected )
-        {
-            renderFlags |= wxPGCellRenderer::Selected;
-#if wxPG_REFRESH_CONTROLS_AFTER_REPAINT
-            wasSelectedPainted = true;
-#endif
-        }
-
-        wxColour rowBgCol;
+        //
+        // Need to override row colours?
         wxColour rowFgCol;
-        wxBrush rowBgBrush;
+        wxColour rowBgCol;
 
-        if ( p->IsCategory() )
-        {
-            if ( p->m_fgColIndex == 0 )
-                rowFgCol = m_colCapFore;
-            else
-                rowFgCol = *(wxPGColour*)m_arrFgCols[p->m_fgColIndex];
-            rowBgBrush = wxBrush(m_colCapBack);
-        }
-        else if ( p != selected )
+        bool isSelected = state->DoIsPropertySelected(p);
+
+        if ( !isSelected )
         {
             // Disabled may get different colour.
             if ( !p->IsEnabled() )
+            {
+                renderFlags |= wxPGCellRenderer::Disabled |
+                               wxPGCellRenderer::DontUseCellFgCol;
                 rowFgCol = m_colDisPropFore;
-            else
-                rowFgCol = *(wxPGColour*)m_arrFgCols[p->m_fgColIndex];
-
-            rowBgBrush = *(wxPGBrush*)m_arrBgBrushes[p->m_bgColIndex];
+            }
         }
         else
         {
-            // Selected gets different colour.
-            if ( reallyFocused )
-            {
-                rowFgCol = m_colSelFore;
-                rowBgBrush = wxBrush(m_colSelBack);
-            }
-            else if ( isEnabled )
+#if wxPG_REFRESH_CONTROLS_AFTER_REPAINT
+            if ( p == firstSelected )
+                wasSelectedPainted = true;
+#endif
+
+            renderFlags |= wxPGCellRenderer::Selected;
+
+            if ( !p->IsCategory() )
             {
-                rowFgCol = *(wxPGColour*)m_arrFgCols[p->m_fgColIndex];
-                rowBgBrush = marginBrush;
+                renderFlags |= wxPGCellRenderer::DontUseCellFgCol |
+                               wxPGCellRenderer::DontUseCellBgCol;
+
+                if ( reallyFocused && p == firstSelected )
+                {
+                    rowFgCol = m_colSelFore;
+                    rowBgCol = selBackCol;
+                }
+                else if ( isPgEnabled )
+                {
+                    rowFgCol = m_colPropFore;
+                    if ( p == firstSelected )
+                        rowBgCol = m_colMargin;
+                    else
+                        rowBgCol = selBackCol;
+                }
+                else
+                {
+                    rowFgCol = m_colDisPropFore;
+                    rowBgCol = selBackCol;
+                }
             }
-            else
+        }
+
+        wxBrush rowBgBrush;
+
+        if ( rowBgCol.IsOk() )
+            rowBgBrush = wxBrush(rowBgCol);
+
+        if ( HasInternalFlag(wxPG_FL_CELL_OVERRIDES_SEL) )
+            renderFlags = renderFlags & ~wxPGCellRenderer::DontUseCellColours;
+
+        //
+        // Fill additional margin area with background colour of first cell
+        if ( greyDepthX < textMarginHere )
+        {
+            if ( !(renderFlags & wxPGCellRenderer::DontUseCellBgCol) )
             {
-                rowFgCol = m_colDisPropFore;
-                rowBgBrush = wxBrush(m_colSelBack);
+                wxPGCell& cell = p->GetCell(0);
+                rowBgCol = cell.GetBgCol();
+                rowBgBrush = wxBrush(rowBgCol);
             }
+            dc.SetBrush(rowBgBrush);
+            dc.SetPen(rowBgCol);
+            dc.DrawRectangle(greyDepthX+1, y,
+                             textMarginHere-greyDepthX, lh-1);
         }
 
         bool fontChanged = false;
 
+        // Expander button rectangle
         wxRect butRect( ((p->m_depth - 1) * m_subgroup_extramargin) - xRelMod,
                         y,
                         m_marginWidth,
@@ -2168,18 +2310,22 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc,
 
         if ( p->IsCategory() )
         {
-            // Captions are all cells merged as one
+            // Captions have their cell areas merged as one
             dc.SetFont(m_captionFont);
             fontChanged = true;
             wxRect cellRect(greyDepthX, y, gridWidth - greyDepth + 2, rowHeight-1 );
 
-            dc.SetBrush(rowBgBrush);
-            dc.SetPen(rowBgBrush.GetColour());
-            dc.SetTextForeground(rowFgCol);
+            if ( renderFlags & wxPGCellRenderer::DontUseCellBgCol )
+            {
+                dc.SetBrush(rowBgBrush);
+                dc.SetPen(rowBgCol);
+            }
 
-            dc.DrawRectangle(cellRect);
+            if ( renderFlags & wxPGCellRenderer::DontUseCellFgCol )
+            {
+                dc.SetTextForeground(rowFgCol);
+            }
 
-            // Foreground
             wxPGCellRenderer* renderer = p->GetCellRenderer(0);
             renderer->Render( dc, cellRect, this, p, 0, -1, renderFlags );
 
@@ -2197,7 +2343,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;
 
@@ -2205,31 +2352,61 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc,
             {
                 cellRect.width = nextCellWidth - 1;
 
-                bool ctrlCell = false;
+                wxWindow* cellEditor = NULL;
+                int cellRenderFlags = renderFlags;
+
+                // Tree Item Button (must be drawn before clipping is set up)
+                if ( ci == 0 && !HasFlag(wxPG_HIDE_MARGIN) && p->HasVisibleChildren() )
+                    DrawExpanderButton( dc, butRect, p );
 
                 // Background
-                if ( p == selected && m_wndEditor && ci == 1 )
+                if ( isSelected && (ci == 1 || ci == m_selColumn) )
                 {
-                    wxColour editorBgCol = GetEditorControl()->GetBackgroundColour();
-                    dc.SetBrush(editorBgCol);
-                    dc.SetPen(editorBgCol);
-                    dc.SetTextForeground(m_colPropFore);
+                    if ( p == firstSelected )
+                    {
+                        if ( ci == 1 && m_wndEditor )
+                            cellEditor = m_wndEditor;
+                        else if ( ci == m_selColumn && m_labelEditor )
+                            cellEditor = m_labelEditor;
+                    }
 
-                    if ( m_dragStatus == 0 && !(m_iFlags & wxPG_FL_CUR_USES_CUSTOM_IMAGE) )
-                        ctrlCell = true;
+                    if ( cellEditor )
+                    {
+                        wxColour editorBgCol =
+                            cellEditor->GetBackgroundColour();
+                        dc.SetBrush(editorBgCol);
+                        dc.SetPen(editorBgCol);
+                        dc.SetTextForeground(m_colPropFore);
+                        dc.DrawRectangle(cellRect);
+
+                        if ( m_dragStatus != 0 ||
+                             (m_iFlags & wxPG_FL_CUR_USES_CUSTOM_IMAGE) )
+                            cellEditor = NULL;
+                    }
+                    else
+                    {
+                        dc.SetBrush(m_colPropBack);
+                        dc.SetPen(m_colPropBack);
+                        dc.SetTextForeground(m_colDisPropFore);
+                        if ( p->IsEnabled() )
+                            dc.SetTextForeground(rowFgCol);
+                        else
+                            dc.SetTextForeground(m_colDisPropFore);
+                    }
                 }
                 else
                 {
-                    dc.SetBrush(rowBgBrush);
-                    dc.SetPen(rowBgBrush.GetColour());
-                    dc.SetTextForeground(rowFgCol);
-                }
-
-                dc.DrawRectangle(cellRect);
+                    if ( renderFlags & wxPGCellRenderer::DontUseCellBgCol )
+                    {
+                        dc.SetBrush(rowBgBrush);
+                        dc.SetPen(rowBgCol);
+                    }
 
-                // Tree Item Button
-                if ( ci == 0 && !HasFlag(wxPG_HIDE_MARGIN) && p->HasVisibleChildren() )
-                    DrawExpanderButton( dc, butRect, p );
+                    if ( renderFlags & wxPGCellRenderer::DontUseCellFgCol )
+                    {
+                        dc.SetTextForeground(rowFgCol);
+                    }
+                }
 
                 dc.SetClippingRegion(cellRect);
 
@@ -2237,33 +2414,35 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc,
                 cellRect.width -= textXAdd;
 
                 // Foreground
-                if ( !ctrlCell )
+                if ( !cellEditor )
                 {
                     wxPGCellRenderer* renderer;
                     int cmnVal = p->GetCommonValue();
                     if ( cmnVal == -1 || ci != 1 )
                     {
                         renderer = p->GetCellRenderer(ci);
-                        renderer->Render( dc, cellRect, this, p, ci, -1, renderFlags );
+                        renderer->Render( dc, cellRect, this, p, ci, -1,
+                                          cellRenderFlags );
                     }
                     else
                     {
                         renderer = GetCommonValue(cmnVal)->GetRenderer();
-                        renderer->Render( dc, cellRect, this, p, ci, -1, renderFlags );
+                        renderer->Render( dc, cellRect, this, p, ci, -1,
+                                          cellRenderFlags );
                     }
                 }
 
                 cellX += state->m_colWidths[ci];
                 if ( ci < (state->m_colWidths.size()-1) )
                     nextCellWidth = state->m_colWidths[ci+1];
-                cellRect.x = cellX; 
+                cellRect.x = cellX;
                 dc.DestroyClippingRegion(); // Is this really necessary?
                 textXAdd = 0;
             }
         }
 
         if ( fontChanged )
-            dc.SetFont(normalfont);
+            dc.SetFont(normalFont);
 
         y += rowHeight;
     }
@@ -2291,7 +2470,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;
@@ -2308,7 +2487,7 @@ wxRect wxPropertyGrid::GetPropertyRect( const wxPGProperty* p1, const wxPGProper
 
     // If seleced property is inside the range, we'll extend the range to include
     // control's size.
-    wxPGProperty* selected = m_selected;
+    wxPGProperty* selected = GetSelection();
     if ( selected )
     {
         int selectedY = selected->GetY();
@@ -2348,8 +2527,12 @@ void wxPropertyGrid::DrawItems( const wxPGProperty* p1, const wxPGProperty* p2 )
 
 void wxPropertyGrid::RefreshProperty( wxPGProperty* p )
 {
-    if ( p == m_selected )
-        DoSelectProperty(p, wxPG_SEL_FORCE);
+    if ( m_pState->DoIsPropertySelected(p) )
+    {
+        // NB: We must copy the selection.
+        wxArrayPGProperty selection = m_pState->m_selection;
+        DoSetSelection(selection, wxPG_SEL_FORCE);
+    }
 
     DrawItemAndChildren(p);
 }
@@ -2387,11 +2570,10 @@ 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);
+    wxPGProperty* selected = GetSelection();
+    if ( selected && selected->GetParent() == p )
+        RefreshEditor();
 
     const wxPGProperty* lastDrawn = p->GetLastVisibleSubItem();
 
@@ -2423,13 +2605,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;
@@ -2447,8 +2622,7 @@ void wxPropertyGrid::Clear()
 
 bool wxPropertyGrid::EnableCategories( bool enable )
 {
-    if ( !ClearSelection() )
-        return false;
+    DoClearSelection();
 
     if ( enable )
     {
@@ -2498,17 +2672,13 @@ void wxPropertyGrid::SwitchState( wxPropertyGridPageState* pNewState )
     if ( pNewState == m_pState )
         return;
 
-    wxPGProperty* oldSelection = m_selected;
+    wxArrayPGProperty oldSelection = m_pState->m_selection;
 
-    // Deselect
-    if ( m_selected )
-    {
-        bool selRes = ClearSelection();
-        wxPG_CHECK_RET_DBG( selRes,
-                            wxT("failed to deselect a property (editor probably had invalid value)") );
-    }
+    // Call ClearSelection() instead of DoClearSelection()
+    // so that selection clear events are not sent.
+    ClearSelection();
 
-    m_pState->m_selected = oldSelection;
+    m_pState->m_selection = oldSelection;
 
     bool orig_mode = m_pState->IsInNonCatMode();
     bool new_state_mode = pNewState->IsInNonCatMode();
@@ -2536,7 +2706,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 )
@@ -2547,12 +2717,11 @@ 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 )
-            DoSelectProperty( m_pState->m_selected );
+        // Reselect (Use SetSelection() instead of Do-variant so that
+        // events won't be sent).
+        SetSelection(m_pState->m_selection);
 
         RecalculateVirtualSize(0);
         Refresh();
@@ -2563,26 +2732,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 )
@@ -2596,7 +2745,7 @@ void wxPropertyGrid::DoSetSplitterPosition_( int newxpos, bool refresh, int spli
 
     if ( refresh )
     {
-        if ( m_selected )
+        if ( GetSelection() )
             CorrectEditorWidgetSizeX();
 
         Refresh();
@@ -2644,24 +2793,6 @@ wxPGProperty* wxPropertyGrid::GetNearestPaintVisible( wxPGProperty* p ) const
 
 }
 
-// -----------------------------------------------------------------------
-
-void wxPropertyGrid::SetButtonShortcut( int keycode, bool ctrlDown, bool altDown )
-{
-    if ( keycode )
-    {
-        m_pushButKeyCode = keycode;
-        m_pushButKeyCodeNeedsCtrl = ctrlDown ? 1 : 0;
-        m_pushButKeyCodeNeedsAlt = altDown ? 1 : 0;
-    }
-    else
-    {
-        m_pushButKeyCode = WXK_DOWN;
-        m_pushButKeyCodeNeedsCtrl = 0;
-        m_pushButKeyCodeNeedsAlt = 1;
-    }
-}
-
 // -----------------------------------------------------------------------
 // Methods related to change in value, value modification and sending events
 // -----------------------------------------------------------------------
@@ -2677,7 +2808,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;
@@ -2685,14 +2816,16 @@ bool wxPropertyGrid::CommitChangesFromEditor( wxUint32 flags )
         return false;
     }
 
+    wxPGProperty* selected = GetSelection();
+
     if ( m_wndEditor &&
          IsEditorsValueModified() &&
          (m_iFlags & wxPG_FL_INITIALIZED) &&
-         m_selected )
+         selected )
     {
         m_inCommitChangesFromEditor = 1;
 
-        wxVariant variant(m_selected->GetValueRef());
+        wxVariant variant(selected->GetValueRef());
         bool valueIsPending = false;
 
         // JACS - necessary to avoid new focus being found spuriously within OnIdle
@@ -2705,10 +2838,13 @@ bool wxPropertyGrid::CommitChangesFromEditor( wxUint32 flags )
         m_chgInfo_changedProperty = NULL;
 
         // If truly modified, schedule value as pending.
-        if ( m_selected->GetEditorClass()->GetValueFromControl( variant, m_selected, GetEditorControl() ) )
+        if ( selected->GetEditorClass()->
+                GetValueFromControl( variant,
+                                     selected,
+                                     GetEditorControl() ) )
         {
             if ( DoEditorValidate() &&
-                 PerformValidation(m_selected, variant) )
+                 PerformValidation(selected, variant) )
             {
                 valueIsPending = true;
             }
@@ -2734,18 +2870,18 @@ bool wxPropertyGrid::CommitChangesFromEditor( wxUint32 flags )
                 m_curFocused = oldFocus;
             }
 
-            res = OnValidationFailure(m_selected, variant);
+            res = OnValidationFailure(selected, variant);
 
             // Now prevent further validation failure messages
             if ( res )
             {
                 EditorsValueWasNotModified();
-                OnValidationFailureReset(m_selected);
+                OnValidationFailureReset(selected);
             }
         }
         else if ( valueIsPending )
         {
-            DoPropertyChanged( m_selected, flags );
+            DoPropertyChanged( selected, flags );
             EditorsValueWasNotModified();
         }
 
@@ -2757,7 +2893,8 @@ bool wxPropertyGrid::CommitChangesFromEditor( wxUint32 flags )
 
 // -----------------------------------------------------------------------
 
-bool wxPropertyGrid::PerformValidation( wxPGProperty* p, wxVariant& pendingValue )
+bool wxPropertyGrid::PerformValidation( wxPGProperty* p, wxVariant& pendingValue,
+                                        int flags )
 {
     //
     // Runs all validation functionality.
@@ -2826,33 +2963,37 @@ bool wxPropertyGrid::PerformValidation( wxPGProperty* p, wxVariant& pendingValue
 
     wxVariant evtChangingValue = value;
 
-    // FIXME: After proper ValueToString()s added, remove
-    // this. It is just a temporary fix, as evt_changing
-    // will simply not work for wxPG_PROP_COMPOSED_VALUE
-    // (unless it is selected, and textctrl editor is open).
-    if ( changedProperty->HasFlag(wxPG_PROP_COMPOSED_VALUE) )
+    if ( flags & SendEvtChanging )
     {
-        evtChangingProperty = baseChangedProperty;
-        if ( evtChangingProperty != p )
-        {
-            evtChangingProperty->AdaptListToValue( bcpPendingList, &evtChangingValue );
-        }
-        else
+        // FIXME: After proper ValueToString()s added, remove
+        // this. It is just a temporary fix, as evt_changing
+        // will simply not work for wxPG_PROP_COMPOSED_VALUE
+        // (unless it is selected, and textctrl editor is open).
+        if ( changedProperty->HasFlag(wxPG_PROP_COMPOSED_VALUE) )
         {
-            evtChangingValue = pendingValue;
+            evtChangingProperty = baseChangedProperty;
+            if ( evtChangingProperty != p )
+            {
+                evtChangingProperty->AdaptListToValue( bcpPendingList, &evtChangingValue );
+            }
+            else
+            {
+                evtChangingValue = pendingValue;
+            }
         }
-    }
 
-    if ( evtChangingProperty->HasFlag(wxPG_PROP_COMPOSED_VALUE) )
-    {
-        if ( changedProperty == m_selected )
-        {
-            wxASSERT( m_wndEditor->IsKindOf(CLASSINFO(wxTextCtrl)) );
-            evtChangingValue = ((wxTextCtrl*)m_wndEditor)->GetValue();
-        }
-        else
+        if ( evtChangingProperty->HasFlag(wxPG_PROP_COMPOSED_VALUE) )
         {
-            wxLogDebug(wxT("WARNING: wxEVT_PG_CHANGING is about to happen with old value."));
+            if ( changedProperty == GetSelection() )
+            {
+                wxWindow* editor = GetEditorControl();
+                wxASSERT( editor->IsKindOf(CLASSINFO(wxTextCtrl)) );
+                evtChangingValue = wxStaticCast(editor, wxTextCtrl)->GetValue();
+            }
+            else
+            {
+                wxLogDebug(wxT("WARNING: wxEVT_PG_CHANGING is about to happen with old value."));
+            }
         }
     }
 
@@ -2874,9 +3015,21 @@ bool wxPropertyGrid::PerformValidation( wxPGProperty* p, wxVariant& pendingValue
             return false;
     }
 
-    // SendEvent returns true if event was vetoed
-    if ( SendEvent( wxEVT_PG_CHANGING, evtChangingProperty, &evtChangingValue, 0 ) )
-        return false;
+    if ( flags & SendEvtChanging )
+    {
+        // SendEvent returns true if event was vetoed
+        if ( SendEvent( wxEVT_PG_CHANGING, evtChangingProperty,
+                        &evtChangingValue ) )
+            return false;
+    }
+
+    if ( flags & IsStandaloneValidation )
+    {
+        // If called in 'generic' context, we need to reset
+        // m_chgInfo_changedProperty and write back translated value.
+        m_chgInfo_changedProperty = NULL;
+        pendingValue = value;
+    }
 
     return true;
 }
@@ -2908,11 +3061,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 == GetSelection() )
+    {
+        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;
@@ -2923,28 +3099,34 @@ bool wxPropertyGrid::DoOnValidationFailure( wxPGProperty* property, wxVariant& W
     if ( (vfb & wxPG_VFB_MARK_CELL) &&
          !property->HasFlag(wxPG_PROP_INVALID_VALUE) )
     {
-        wxASSERT_MSG( !property->GetCell(0) && !property->GetCell(1),
-                      wxT("Currently wxPG_VFB_MARK_CELL only works with properties with standard first two cells") );
+        unsigned int colCount = m_pState->GetColumnCount();
+
+        // We need backup marked property's cells
+        m_propCellsBackup = property->m_cells;
+
+        wxColour vfbFg = *wxWHITE;
+        wxColour vfbBg = *wxRED;
+
+        property->EnsureCells(colCount);
 
-        if ( !property->GetCell(0) && !property->GetCell(1) )
+        for ( unsigned int i=0; i<colCount; i++ )
         {
-            wxColour vfbFg = *wxWHITE;
-            wxColour vfbBg = *wxRED;
-            property->SetCell(0, new wxPGCell(property->GetLabel(), wxNullBitmap, vfbFg, vfbBg));
-            property->SetCell(1, new wxPGCell(property->GetDisplayedString(), wxNullBitmap, vfbFg, vfbBg));
+            wxPGCell& cell = property->m_cells[i];
+            cell.SetFgCol(vfbFg);
+            cell.SetBgCol(vfbBg);
+        }
 
-            DrawItemAndChildren(property);
+        DrawItemAndChildren(property);
 
-            if ( property == m_selected )
-            {
-                SetInternalFlag(wxPG_FL_CELL_OVERRIDES_SEL);
+        if ( property == GetSelection() )
+        {
+            SetInternalFlag(wxPG_FL_CELL_OVERRIDES_SEL);
 
-                wxWindow* editor = GetEditorControl();
-                if ( editor )
-                {
-                    editor->SetForegroundColour(vfbFg);
-                    editor->SetBackgroundColour(vfbBg);
-                }
+            wxWindow* editor = GetEditorControl();
+            if ( editor )
+            {
+                editor->SetForegroundColour(vfbFg);
+                editor->SetBackgroundColour(vfbBg);
             }
         }
     }
@@ -2954,7 +3136,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);
     }
@@ -2970,12 +3152,12 @@ void wxPropertyGrid::DoOnValidationFailureReset( wxPGProperty* property )
 
     if ( vfb & wxPG_VFB_MARK_CELL )
     {
-        property->SetCell(0, NULL);
-        property->SetCell(1, NULL);
+        // Revert cells
+        property->m_cells = m_propCellsBackup;
 
         ClearInternalFlag(wxPG_FL_CELL_OVERRIDES_SEL);
 
-        if ( property == m_selected && GetEditorControl() )
+        if ( property == GetSelection() && GetEditorControl() )
         {
             // Calling this will recreate the control, thus resetting its colour
             RefreshProperty(property);
@@ -2996,6 +3178,7 @@ bool wxPropertyGrid::DoPropertyChanged( wxPGProperty* p, unsigned int selFlags )
         return true;
 
     wxWindow* editor = GetEditorControl();
+    wxPGProperty* selected = GetSelection();
 
     m_pState->m_anyModified = 1;
 
@@ -3022,7 +3205,7 @@ bool wxPropertyGrid::DoPropertyChanged( wxPGProperty* p, unsigned int selFlags )
     if ( !(p->m_flags & wxPG_PROP_MODIFIED) )
     {
         p->m_flags |= wxPG_PROP_MODIFIED;
-        if ( p == m_selected && (m_windowStyle & wxPG_BOLD_MODIFIED) )
+        if ( p == selected && (m_windowStyle & wxPG_BOLD_MODIFIED) )
         {
             if ( editor )
                 SetCurControlBoldFont();
@@ -3039,7 +3222,7 @@ bool wxPropertyGrid::DoPropertyChanged( wxPGProperty* p, unsigned int selFlags )
     {
         pwc->m_flags |= wxPG_PROP_MODIFIED;
 
-        if ( pwc == m_selected && (m_windowStyle & wxPG_BOLD_MODIFIED) )
+        if ( pwc == selected && (m_windowStyle & wxPG_BOLD_MODIFIED) )
         {
             if ( editor )
                 SetCurControlBoldFont();
@@ -3057,8 +3240,7 @@ bool wxPropertyGrid::DoPropertyChanged( wxPGProperty* p, unsigned int selFlags )
     // control.
     if ( selFlags & wxPG_SEL_DIALOGVAL )
     {
-        if ( editor )
-            p->GetEditorClass()->UpdateControl(p, editor);
+        RefreshEditor();
     }
     else
     {
@@ -3079,12 +3261,12 @@ bool wxPropertyGrid::DoPropertyChanged( wxPGProperty* p, unsigned int selFlags )
 
         while ( pwc != changedProperty )
         {
-            SendEvent( wxEVT_PG_CHANGED, pwc, NULL, selFlags );
+            SendEvent( wxEVT_PG_CHANGED, pwc, NULL );
             pwc = pwc->GetParent();
         }
     }
 
-    SendEvent( wxEVT_PG_CHANGED, changedProperty, NULL, selFlags );
+    SendEvent( wxEVT_PG_CHANGED, changedProperty, NULL );
 
     m_inDoPropertyChanged = 0;
 
@@ -3114,55 +3296,61 @@ bool wxPropertyGrid::ChangePropertyValue( wxPGPropArg id, wxVariant newValue )
 
 // -----------------------------------------------------------------------
 
-// Runs wxValidator for the selected property
-bool wxPropertyGrid::DoEditorValidate()
+wxVariant wxPropertyGrid::GetUncommittedPropertyValue()
 {
-    return true;
+    wxPGProperty* prop = GetSelectedProperty();
+
+    if ( !prop )
+        return wxNullVariant;
+
+    wxTextCtrl* tc = GetEditorTextCtrl();
+    wxVariant value = prop->GetValue();
+
+    if ( !tc || !IsEditorsValueModified() )
+        return value;
+
+    if ( !prop->StringToValue(value, tc->GetValue()) )
+        return value;
+
+    if ( !PerformValidation(prop, value, IsStandaloneValidation) )
+        return prop->GetValue();
+
+    return value;
 }
 
 // -----------------------------------------------------------------------
 
-bool wxPropertyGrid::ProcessEvent(wxEvent& event)
+// Runs wxValidator for the selected property
+bool wxPropertyGrid::DoEditorValidate()
 {
-    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((wxCommandEvent&)event);
-            return true;
-        }
-    }
-    return wxPanel::ProcessEvent(event);
+    return true;
 }
 
 // -----------------------------------------------------------------------
 
-// NB: It may really not be wxCommandEvent - must check if necessary
-//     (usually not).
-void wxPropertyGrid::OnCustomEditorEvent( wxCommandEvent &event )
+void wxPropertyGrid::HandleCustomEditorEvent( wxEvent &event )
 {
-    wxPGProperty* selected = m_selected;
+    wxPGProperty* selected = GetSelection();
 
-    //
     // Somehow, event is handled after property has been deselected.
     // Possibly, but very rare.
-    if ( !selected )
+    if ( !selected ||
+          selected->HasFlag(wxPG_PROP_BEING_DELETED) ||
+          // Also don't handle editor event if wxEVT_PG_CHANGED or
+          // similar is currently doing something (showing a
+          // message box, for instance).
+          m_processedEvent )
         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;
@@ -3184,7 +3372,7 @@ void wxPropertyGrid::OnCustomEditorEvent( wxCommandEvent &event )
         m_prevTcValue = newTcValue;
     }
 
-    SetInternalFlag(wxPG_FL_IN_ONCUSTOMEDITOREVENT);
+    SetInternalFlag(wxPG_FL_IN_HANDLECUSTOMEDITOREVENT);
 
     bool validationFailure = false;
     bool buttonWasHandled = false;
@@ -3208,17 +3396,19 @@ void wxPropertyGrid::OnCustomEditorEvent( wxCommandEvent &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,
+                                                      selected,
+                                                      wnd ) )
                         valueIsPending = true;
                 }
                 else
@@ -3231,7 +3421,7 @@ void wxPropertyGrid::OnCustomEditorEvent( wxCommandEvent &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
@@ -3244,10 +3434,10 @@ void wxPropertyGrid::OnCustomEditorEvent( wxCommandEvent &event )
     }
 
     if ( !validationFailure && valueIsPending )
-        if ( !PerformValidation(m_selected, pendingValue) )
+        if ( !PerformValidation(selected, pendingValue) )
             validationFailure = true;
 
-    if ( validationFailure )
+    if ( validationFailure)
     {
         OnValidationFailure(selected, pendingValue);
     }
@@ -3258,7 +3448,6 @@ void wxPropertyGrid::OnCustomEditorEvent( wxCommandEvent &event )
         DoPropertyChanged(selected, selFlags);
         EditorsValueWasNotModified();
 
-        //
         // Regardless of editor type, unfocus editor on
         // text-editing related enter press.
         if ( event.GetEventType() == wxEVT_COMMAND_TEXT_ENTER )
@@ -3270,6 +3459,13 @@ void wxPropertyGrid::OnCustomEditorEvent( wxCommandEvent &event )
     {
         // No value after all
 
+        // Regardless of editor type, unfocus editor on
+        // text-editing related enter press.
+        if ( event.GetEventType() == wxEVT_COMMAND_TEXT_ENTER )
+        {
+            SetFocusOnCanvas();
+        }
+
         // Let unhandled button click events go to the parent
         if ( !buttonWasHandled && event.GetEventType() == wxEVT_COMMAND_BUTTON_CLICKED )
         {
@@ -3278,7 +3474,7 @@ void wxPropertyGrid::OnCustomEditorEvent( wxCommandEvent &event )
         }
     }
 
-    ClearInternalFlag(wxPG_FL_IN_ONCUSTOMEDITOREVENT);
+    ClearInternalFlag(wxPG_FL_IN_HANDLECUSTOMEDITOREVENT);
 }
 
 // -----------------------------------------------------------------------
@@ -3289,24 +3485,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
       );
 }
@@ -3403,9 +3600,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 )
 {
@@ -3432,52 +3657,81 @@ void wxPropertyGrid::SetupChildEventHandling( wxWindow* argWnd )
             wxMouseEventHandler(wxPropertyGrid::OnMouseEntry),
             NULL, this);
     }
-    else
-    {
-        argWnd->Connect(id, wxEVT_NAVIGATION_KEY,
-            wxNavigationKeyEventHandler(wxPropertyGrid::OnNavigationKey));
-    }
+
+    wxPropertyGridEditorEventForwarder* forwarder;
+    forwarder = new wxPropertyGridEditorEventForwarder(this);
+    argWnd->PushEventHandler(forwarder);
 
     argWnd->Connect(id, wxEVT_KEY_DOWN,
-        wxKeyEventHandler(wxPropertyGrid::OnChildKeyDown),
-        NULL, this);
-    argWnd->Connect(id, wxEVT_KEY_UP,
-        wxKeyEventHandler(wxPropertyGrid::OnChildKeyUp),
-        NULL, this);
-    argWnd->Connect(id, wxEVT_KILL_FOCUS,
-        wxFocusEventHandler(wxPropertyGrid::OnFocusEvent),
+        wxCharEventHandler(wxPropertyGrid::OnChildKeyDown),
         NULL, this);
 }
 
+void wxPropertyGrid::DestroyEditorWnd( wxWindow* wnd )
+{
+    if ( !wnd )
+        return;
+
+    wnd->Hide();
+
+    // Do not free editors immediately (for sake of processing events)
+    wxPendingDelete.Append(wnd);
+}
+
 void wxPropertyGrid::FreeEditors()
 {
+    //
+    // Return focus back to canvas from children (this is required at least for
+    // GTK+, which, unlike Windows, clears focus when control is destroyed
+    // instead of moving it to closest parent).
+    wxWindow* focus = wxWindow::FindFocus();
+    if ( focus )
+    {
+        wxWindow* parent = focus->GetParent();
+        while ( parent )
+        {
+            if ( parent == m_canvas )
+            {
+                SetFocusOnCanvas();
+                break;
+            }
+            parent = parent->GetParent();
+        }
+    }
+
     // Do not free editors immediately if processing events
     if ( m_wndEditor2 )
     {
-        m_windowsToDelete.push_back(m_wndEditor2);
+        wxEvtHandler* handler = m_wndEditor2->PopEventHandler(false);
         m_wndEditor2->Hide();
-        m_wndEditor2 = (wxWindow*) NULL;
+        wxPendingDelete.Append( handler );
+        DestroyEditorWnd(m_wndEditor2);
+        m_wndEditor2 = NULL;
     }
 
     if ( m_wndEditor )
     {
-        m_windowsToDelete.push_back(m_wndEditor);
+        wxEvtHandler* handler = m_wndEditor->PopEventHandler(false);
         m_wndEditor->Hide();
-        m_wndEditor = (wxWindow*) NULL;
+        wxPendingDelete.Append( handler );
+        DestroyEditorWnd(m_wndEditor);
+        m_wndEditor = NULL;
     }
 }
 
 // Call with NULL to de-select property
 bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags )
 {
-    wxPanel* canvas = GetPanel();
-
     /*
     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 )
@@ -3485,47 +3739,58 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags )
 
     m_inDoSelectProperty = 1;
 
-    wxPGProperty* prev = m_selected;
-
-    //
-    // Delete windows pending for deletion
-    if ( !m_inDoPropertyChanged && m_windowsToDelete.size() )
-    {
-        unsigned int i;
-
-        for ( i=0; i<m_windowsToDelete.size(); i++ )
-            delete m_windowsToDelete[i];
-
-        m_windowsToDelete.clear();
-    }
-
     if ( !m_pState )
     {
         m_inDoSelectProperty = 0;
         return false;
     }
 
-    //
+    wxArrayPGProperty prevSelection = m_pState->m_selection;
+    wxPGProperty* prevFirstSel;
+
+    if ( prevSelection.size() > 0 )
+        prevFirstSel = prevSelection[0];
+    else
+        prevFirstSel = NULL;
+
+    if ( prevFirstSel && prevFirstSel->HasFlag(wxPG_PROP_BEING_DELETED) )
+        prevFirstSel = NULL;
+
+    // Always send event, as this is indirect call
+    DoEndLabelEdit(true, wxPG_SEL_NOVALIDATE);
+
+/*
+    if ( prevFirstSel )
+        wxPrintf( "Selected %s\n", prevFirstSel->GetClassInfo()->GetClassName() );
+    else
+        wxPrintf( "None selected\n" );
+
+    if (p)
+        wxPrintf( "P =  %s\n", p->GetClassInfo()->GetClassName() );
+    else
+        wxPrintf( "P = NULL\n" );
+*/
+
     // If we are frozen, then just set the values.
     if ( m_frozen )
     {
         m_iFlags &= ~(wxPG_FL_ABNORMAL_EDITOR);
         m_editorFocused = 0;
-        m_selected = p;
-        m_selColumn = 1;
-        m_pState->m_selected = p;
+        m_pState->DoSetSelection(p);
 
         // If frozen, always free controls. But don't worry, as Thaw will
         // recall SelectProperty to recreate them.
         FreeEditors();
 
         // Prevent any further selection measures in this call
-        p = (wxPGProperty*) NULL;
+        p = NULL;
     }
     else
     {
         // Is it the same?
-        if ( m_selected == p && !(flags & wxPG_SEL_FORCE) )
+        if ( prevFirstSel == p &&
+             prevSelection.size() <= 1 &&
+             !(flags & wxPG_SEL_FORCE) )
         {
             // Only set focus if not deselecting
             if ( p )
@@ -3550,13 +3815,12 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags )
 
         //
         // First, deactivate previous
-        if ( m_selected )
+        if ( prevFirstSel )
         {
-
-            OnValidationFailureReset(m_selected);
+            OnValidationFailureReset(prevFirstSel);
 
             // Must double-check if this is an selected in case of forceswitch
-            if ( p != prev )
+            if ( p != prevFirstSel )
             {
                 if ( !CommitChangesFromEditor(flags) )
                 {
@@ -3569,13 +3833,6 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags )
             }
 
             FreeEditors();
-            m_selColumn = -1;
-
-            m_selected = (wxPGProperty*) NULL;
-            m_pState->m_selected = (wxPGProperty*) NULL;
-
-            // We need to always fully refresh the grid here
-            Refresh(false);
 
             m_iFlags &= ~(wxPG_FL_ABNORMAL_EDITOR);
             EditorsValueWasNotModified();
@@ -3583,6 +3840,14 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags )
 
         SetInternalFlag(wxPG_FL_IN_SELECT_PROPERTY);
 
+        m_pState->DoSetSelection(p);
+
+        // Redraw unselected
+        for ( unsigned int i=0; i<prevSelection.size(); i++ )
+        {
+            DrawItem(prevSelection[i]);
+        }
+
         //
         // Then, activate the one given.
         if ( p )
@@ -3591,16 +3856,11 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags )
 
             int splitterX = GetSplitterPosition();
             m_editorFocused = 0;
-            m_selected = p;
-            m_pState->m_selected = p;
             m_iFlags |= wxPG_FL_PRIMARY_FILLS_ENTIRE;
-            if ( p != prev )
+            if ( p != prevFirstSel )
                 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
@@ -3619,10 +3879,6 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags )
 
                 wxRect grect = GetEditorWidgetRect(p, m_selColumn);
                 wxPoint goodPos = grect.GetPosition();
-            #if wxPG_CREATE_CONTROLS_HIDDEN
-                int coord_adjust = m_height - goodPos.y;
-                goodPos.y += coord_adjust;
-            #endif
 
                 const wxPGEditor* editor = p->GetEditorClass();
                 wxCHECK_MSG(editor, false,
@@ -3637,22 +3893,27 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags )
 
                 m_wndEditor = wndList.m_primary;
                 m_wndEditor2 = wndList.m_secondary;
+                wxWindow* primaryCtrl = GetEditorControl();
+
+                //
+                // Essentially, primaryCtrl == m_wndEditor
+                //
 
                 // NOTE: It is allowed for m_wndEditor to be NULL - in this case
                 //       value is drawn as normal, and m_wndEditor2 is assumed
-                //       to be a right-aligned button that triggers a separate editor
+                //       to be a right-aligned button that triggers a separate editorCtrl
                 //       window.
 
                 if ( m_wndEditor )
                 {
-                    wxASSERT_MSG( m_wndEditor->GetParent() == canvas,
+                    wxASSERT_MSG( m_wndEditor->GetParent() == GetPanel(),
                                   wxT("CreateControls must use result of wxPropertyGrid::GetPanel() as parent of controls.") );
 
                     // Set validator, if any
                 #if wxUSE_VALIDATORS
                     wxValidator* validator = p->GetValidator();
                     if ( validator )
-                        m_wndEditor->SetValidator(*validator);
+                        primaryCtrl->SetValidator(*validator);
                 #endif
 
                     if ( m_wndEditor->GetSize().y > (m_lineHeight+6) )
@@ -3663,18 +3924,6 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags )
                     if ( (p->m_flags & wxPG_PROP_MODIFIED) && (m_windowStyle & wxPG_BOLD_MODIFIED) )
                         SetCurControlBoldFont();
 
-                    //
-                    // Fix TextCtrl indentation
-                #if defined(__WXMSW__) && !defined(__WXWINCE__)
-                    wxTextCtrl* tc = NULL;
-                    if ( m_wndEditor->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)) )
-                        tc = ((wxOwnerDrawnComboBox*)m_wndEditor)->GetTextCtrl();
-                    else
-                        tc = wxDynamicCast(m_wndEditor, wxTextCtrl);
-                    if ( tc )
-                        ::SendMessage(GetHwndOf(tc), EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(0, 0));
-                #endif
-
                     // Store x relative to splitter (we'll need it).
                     m_ctrlXAdjust = m_wndEditor->GetPosition().x - splitterX;
 
@@ -3687,16 +3936,6 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags )
 
                     m_wndEditor->SetSizeHints(3, 3);
 
-                #if wxPG_CREATE_CONTROLS_HIDDEN
-                    m_wndEditor->Show(false);
-                    m_wndEditor->Freeze();
-
-                    goodPos = m_wndEditor->GetPosition();
-                    goodPos.y -= coord_adjust;
-                    m_wndEditor->Move( goodPos );
-                #endif
-
-                    wxWindow* primaryCtrl = GetEditorControl();
                     SetupChildEventHandling(primaryCtrl);
 
                     // Focus and select all (wxTextCtrl, wxComboBox etc)
@@ -3710,7 +3949,7 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags )
 
                 if ( m_wndEditor2 )
                 {
-                    wxASSERT_MSG( m_wndEditor2->GetParent() == canvas,
+                    wxASSERT_MSG( m_wndEditor2->GetParent() == GetPanel(),
                                   wxT("CreateControls must use result of wxPropertyGrid::GetPanel() as parent of controls.") );
 
                     // Get proper id for wndSecondary
@@ -3722,19 +3961,6 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags )
 
                     m_wndEditor2->SetSizeHints(3,3);
 
-                #if wxPG_CREATE_CONTROLS_HIDDEN
-                    wxRect sec_rect = m_wndEditor2->GetRect();
-                    sec_rect.y -= coord_adjust;
-
-                    // Fine tuning required to fix "oversized"
-                    // button disappearance bug.
-                    if ( sec_rect.y < 0 )
-                    {
-                        sec_rect.height += sec_rect.y;
-                        sec_rect.y = 0;
-                    }
-                    m_wndEditor2->SetSize( sec_rect );
-                #endif
                     m_wndEditor2->Show();
 
                     SetupChildEventHandling(m_wndEditor2);
@@ -3768,13 +3994,11 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags )
 
             if ( m_wndEditor )
             {
-            #if wxPG_CREATE_CONTROLS_HIDDEN
-                m_wndEditor->Thaw();
-            #endif
                 m_wndEditor->Show(true);
             }
 
-            DrawItems(p, p);
+            if ( !(flags & wxPG_SEL_NO_REFRESH) )
+                DrawItem(p);
         }
         else
         {
@@ -3795,7 +4019,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);
@@ -3833,7 +4057,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, p, NULL );
 
     return true;
 }
@@ -3842,25 +4067,61 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags )
 
 bool wxPropertyGrid::UnfocusEditor()
 {
-    if ( !m_selected || !m_wndEditor || m_frozen )
+    wxPGProperty* selected = GetSelection();
+
+    if ( !selected || !m_wndEditor || m_frozen )
         return true;
 
     if ( !CommitChangesFromEditor(0) )
         return false;
 
     SetFocusOnCanvas();
-    DrawItem(m_selected);
+    DrawItem(selected);
 
     return true;
 }
 
 // -----------------------------------------------------------------------
 
-// This method is not inline because it called dozens of times
-// (i.e. two-arg function calls create smaller code size).
-bool wxPropertyGrid::DoClearSelection()
+void wxPropertyGrid::RefreshEditor()
+{
+    wxPGProperty* p = GetSelection();
+    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 )
 {
-    return DoSelectProperty((wxPGProperty*)NULL);
+    wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
+
+    int flags = wxPG_SEL_DONT_SEND_EVENT;
+    if ( focus )
+        flags |= wxPG_SEL_FOCUS;
+
+    return DoSelectProperty(p, flags);
 }
 
 // -----------------------------------------------------------------------
@@ -3870,12 +4131,12 @@ bool wxPropertyGrid::DoClearSelection()
 bool wxPropertyGrid::DoCollapse( wxPGProperty* p, bool sendEvents )
 {
     wxPGProperty* pwc = wxStaticCast(p, wxPGProperty);
+    wxPGProperty* selected = GetSelection();
 
     // If active editor was inside collapsed section, then disable it
-    if ( m_selected && m_selected->IsSomeParent (p) )
+    if ( selected && selected->IsSomeParent(p) )
     {
-        if ( !ClearSelection() )
-            return false;
+        DoClearSelection();
     }
 
     // Store dont-center-splitter flag 'cause we need to temporarily set it
@@ -3944,7 +4205,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;
 }
@@ -3956,13 +4217,18 @@ bool wxPropertyGrid::DoHideProperty( wxPGProperty* p, bool hide, int flags )
     if ( m_frozen )
         return m_pState->DoHideProperty(p, hide, flags);
 
-    if ( m_selected &&
-         ( m_selected == p || m_selected->IsSomeParent(p) )
-       )
+    wxArrayPGProperty selection = m_pState->m_selection;  // Must use a copy
+    int selRemoveCount = 0;
+    for ( unsigned int i=0; i<selection.size(); i++ )
+    {
+        wxPGProperty* selected = selection[i];
+        if ( selected == p || selected->IsSomeParent(p) )
         {
-            if ( !ClearSelection() )
+            if ( !DoRemoveFromSelection(p, flags) )
                 return false;
+            selRemoveCount += 1;
         }
+    }
 
     m_pState->DoHideProperty(p, hide, flags);
 
@@ -3989,17 +4255,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;
 
@@ -4010,7 +4269,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;
@@ -4029,7 +4288,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,
@@ -4047,11 +4306,14 @@ void wxPropertyGrid::RecalculateVirtualSize( int forceXPos )
     m_width = width;
     m_height = height;
 
-    m_canvas->SetSize( x, y );
+    // Explicitly pass the position - works around a bug in wxWidgets when the property grid
+    // has a native XP border and a contained window creeps up-and-left when size is set without
+    // the position.
+    m_canvas->SetSize( 0, 0, x, y );
 
     m_pState->CheckColumnWidths();
 
-    if ( m_selected )
+    if ( GetSelection() )
         CorrectEditorWidgetSizeX();
 
     m_iFlags &= ~wxPG_FL_RECALCULATING_VIRTUAL_SIZE;
@@ -4145,22 +4407,36 @@ void wxPropertyGrid::SetFocusOnCanvas()
 
 // selFlags uses same values DoSelectProperty's flags
 // Returns true if event was vetoed.
-bool wxPropertyGrid::SendEvent( int eventType, wxPGProperty* p, wxVariant* pValue, unsigned int WXUNUSED(selFlags) )
+bool wxPropertyGrid::SendEvent( int eventType, wxPGProperty* p,
+                                wxVariant* pValue,
+                                unsigned int selFlags,
+                                unsigned int column )
 {
     // Send property grid event of specific type and with specific property
     wxPropertyGridEvent evt( eventType, m_eventObject->GetId() );
     evt.SetPropertyGrid(this);
     evt.SetEventObject(m_eventObject);
     evt.SetProperty(p);
-    if ( pValue )
+    evt.SetColumn(column);
+    if ( eventType == wxEVT_PG_CHANGING )
     {
+        wxASSERT( pValue );
         evt.SetCanVeto(true);
-        evt.SetupValidationInfo();
         m_validationInfo.m_pValue = pValue;
+        evt.SetupValidationInfo();
+    }
+    else
+    {
+        if ( p )
+            evt.SetPropertyValue(p->GetValue());
+
+        if ( !(selFlags & wxPG_SEL_NOVALIDATE) )
+            evt.SetCanVeto(true);
     }
-    wxEvtHandler* evtHandler = m_eventObject->GetEventHandler();
 
-    evtHandler->ProcessEvent(evt);
+    m_processedEvent = &evt;
+    m_eventObject->HandleWindowEvent(evt);
+    m_processedEvent = NULL;
 
     return evt.WasVetoed();
 }
@@ -4210,7 +4486,9 @@ bool wxPropertyGrid::HandleMouseClick( int x, unsigned int y, wxMouseEvent &even
                      )
                     )
                 {
-                    if ( !DoSelectProperty( p ) )
+                    if ( !AddToSelectionFromInputEvent( p,
+                                                        columnHit,
+                                                        &event ) )
                         return res;
 
                     // On double-click, expand/collapse.
@@ -4230,7 +4508,10 @@ bool wxPropertyGrid::HandleMouseClick( int x, unsigned int y, wxMouseEvent &even
                     m_iFlags |= wxPG_FL_ACTIVATION_BY_CLICK;
                     selFlag = wxPG_SEL_FOCUS;
                 }
-                if ( !DoSelectProperty( p, selFlag ) )
+                if ( !AddToSelectionFromInputEvent( p,
+                                                    columnHit,
+                                                    &event,
+                                                    selFlag ) )
                     return res;
 
                 m_iFlags &= ~(wxPG_FL_ACTIVATION_BY_CLICK);
@@ -4258,9 +4539,13 @@ bool wxPropertyGrid::HandleMouseClick( int x, unsigned int y, wxMouseEvent &even
                     }
                     else if ( m_dragStatus == 0 )
                     {
-                    //
-                    // Begin draggin the splitter
-                    //
+                        //
+                        // Begin draggin the splitter
+                        //
+
+                        // send event
+                        DoEndLabelEdit(true, wxPG_SEL_NOVALIDATE);
+
                         if ( m_wndEditor )
                         {
                             // Changes must be committed here or the
@@ -4321,15 +4606,15 @@ bool wxPropertyGrid::HandleMouseClick( int x, unsigned int y, wxMouseEvent &even
 
 // -----------------------------------------------------------------------
 
-bool wxPropertyGrid::HandleMouseRightClick( int WXUNUSED(x), unsigned int WXUNUSED(y),
-                                            wxMouseEvent& WXUNUSED(event) )
+bool wxPropertyGrid::HandleMouseRightClick( int WXUNUSED(x),
+                                            unsigned int WXUNUSED(y),
+                                            wxMouseEvent& event )
 {
     if ( m_propHover )
     {
         // Select property here as well
         wxPGProperty* p = m_propHover;
-        if ( p != m_selected )
-            DoSelectProperty( p );
+        AddToSelectionFromInputEvent(p, m_colHover, &event);
 
         // Send right click event.
         SendEvent( wxEVT_PG_RIGHT_CLICK, p );
@@ -4341,16 +4626,16 @@ bool wxPropertyGrid::HandleMouseRightClick( int WXUNUSED(x), unsigned int WXUNUS
 
 // -----------------------------------------------------------------------
 
-bool wxPropertyGrid::HandleMouseDoubleClick( int WXUNUSED(x), unsigned int WXUNUSED(y),
-                                             wxMouseEvent& WXUNUSED(event) )
+bool wxPropertyGrid::HandleMouseDoubleClick( int WXUNUSED(x),
+                                             unsigned int WXUNUSED(y),
+                                             wxMouseEvent& event )
 {
     if ( m_propHover )
     {
         // Select property here as well
         wxPGProperty* p = m_propHover;
 
-        if ( p != m_selected )
-            DoSelectProperty( p );
+        AddToSelectionFromInputEvent(p, m_colHover, &event);
 
         // Send double-click event.
         SendEvent( wxEVT_PG_DOUBLE_CLICK, m_propHover );
@@ -4400,6 +4685,8 @@ bool wxPropertyGrid::HandleMouseMove( int x, unsigned int y, wxMouseEvent &event
     int columnHit = state->HitTestH( x, &splitterHit, &splitterHitOffset );
     int splitterX = x - splitterHitOffset;
 
+    m_colHover = columnHit;
+
     if ( m_dragStatus > 0 )
     {
         if ( x > (m_marginWidth + wxPG_DRAG_MARGIN) &&
@@ -4417,7 +4704,7 @@ bool wxPropertyGrid::HandleMouseMove( int x, unsigned int y, wxMouseEvent &event
                 state->DoSetSplitterPosition( newSplitterX, m_draggedSplitter, false );
                 state->m_fSplitterX = (float) newSplitterX;
 
-                if ( m_selected )
+                if ( GetSelection() )
                     CorrectEditorWidgetSizeX();
 
                 Update();
@@ -4442,9 +4729,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
@@ -4507,7 +4794,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 );
@@ -4556,8 +4843,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() )
             {
 
@@ -4577,6 +4863,38 @@ bool wxPropertyGrid::HandleMouseMove( int x, unsigned int y, wxMouseEvent &event
                     CustomSetCursor( wxCURSOR_ARROW );
             }
         }
+
+        //
+        // Multi select by dragging
+        //
+        if ( (GetExtraStyle() & wxPG_EX_MULTIPLE_SELECTION) &&
+             event.LeftIsDown() &&
+             m_propHover &&
+             GetSelection() &&
+             columnHit != 1 &&
+             !state->DoIsPropertySelected(m_propHover) )
+        {
+            // Additional requirement is that the hovered property
+            // is adjacent to edges of selection.
+            const wxArrayPGProperty& selection = GetSelectedProperties();
+
+            // Since categories cannot be selected along with 'other'
+            // properties, exclude them from iterator flags.
+            int iterFlags = wxPG_ITERATE_VISIBLE & (~wxPG_PROP_CATEGORY);
+
+            for ( int i=(selection.size()-1); i>=0; i-- )
+            {
+                // TODO: This could be optimized by keeping track of
+                //       which properties are at the edges of selection.
+                wxPGProperty* selProp = selection[i];
+                if ( state->ArePropertiesAdjacent(m_propHover, selProp,
+                                                  iterFlags) )
+                {
+                    DoAddToSelection(m_propHover);
+                    break;
+                }
+            }
+        }
     }
     return true;
 }
@@ -4626,8 +4944,9 @@ bool wxPropertyGrid::HandleMouseUp( int x, unsigned int WXUNUSED(y),
         m_dragStatus = 0;
 
         // Control background needs to be cleared
-        if ( !(m_iFlags & wxPG_FL_PRIMARY_FILLS_ENTIRE) && m_selected )
-            DrawItem( m_selected );
+        wxPGProperty* selected = GetSelection();
+        if ( !(m_iFlags & wxPG_FL_PRIMARY_FILLS_ENTIRE) && selected )
+            DrawItem( selected );
 
         if ( m_wndEditor )
         {
@@ -4658,19 +4977,19 @@ bool wxPropertyGrid::OnMouseCommon( wxMouseEvent& event, int* px, int* py )
     int ux = event.m_x;
     int uy = event.m_y;
 
-    wxWindow* wnd = m_wndEditor;
+    wxWindow* wnd = GetEditorControl();
 
     // Hide popup on clicks
     if ( event.GetEventType() != wxEVT_MOTION )
         if ( wnd && wnd->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)) )
         {
-            ((wxOwnerDrawnComboBox*)m_wndEditor)->HidePopup();
+            ((wxOwnerDrawnComboBox*)wnd)->HidePopup();
         }
 
     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) ||
@@ -4813,8 +5132,6 @@ bool wxPropertyGrid::OnMouseChildCommon( wxMouseEvent &event, int* px, int *py )
     int x, y;
     event.GetPosition(&x,&y);
 
-    AdjustPosForClipperWindow( topCtrlWnd, &x, &y );
-
     int splitterX = GetSplitterPosition();
 
     wxRect r = topCtrlWnd->GetRect();
@@ -4853,8 +5170,10 @@ void wxPropertyGrid::OnMouseRightClickChild( wxMouseEvent &event )
     // but that should not matter (right click is about item, not position).
     wxPoint pt = m_wndEditor->GetPosition();
     CalcUnscrolledPosition( event.m_x + pt.x, event.m_y + pt.y, &x, &y );
-    wxASSERT( m_selected );
-    m_propHover = m_selected;
+
+    // FIXME: Used to set m_propHover to selection here. Was it really
+    //        necessary?
+
     bool res = HandleMouseRightClick(x,y,event);
     if ( !res ) event.Skip();
 }
@@ -4883,17 +5202,6 @@ void wxPropertyGrid::OnMouseUpChild( wxMouseEvent &event )
 // wxPropertyGrid keyboard event handling
 // -----------------------------------------------------------------------
 
-void wxPropertyGrid::SendNavigationKeyEvent( int dir )
-{
-    wxNavigationKeyEvent evt;
-    evt.SetFlags(wxNavigationKeyEvent::FromTab|
-                 (dir?wxNavigationKeyEvent::IsForward:
-                      wxNavigationKeyEvent::IsBackward));
-    evt.SetEventObject(this);
-    m_canvas->GetEventHandler()->AddPendingEvent(evt);
-}
-
-
 int wxPropertyGrid::KeyEventToActions(wxKeyEvent &event, int* pSecond) const
 {
     // Translates wxKeyEvent to wxPG_ACTION_XXX
@@ -4944,397 +5252,246 @@ void wxPropertyGrid::AddActionTrigger( int action, int keycode, int modifiers )
 void wxPropertyGrid::ClearActionTriggers( int action )
 {
     wxPGHashMapI2I::iterator it;
+    bool didSomething;
 
-    for ( it = m_actionTriggers.begin(); it != m_actionTriggers.end(); it++ )
+    do
     {
-        if ( it->second == action )
+        didSomething = false;
+
+        for ( it = m_actionTriggers.begin();
+              it != m_actionTriggers.end();
+              it++ )
         {
-            m_actionTriggers.erase(it);
+            if ( it->second == action )
+            {
+                m_actionTriggers.erase(it);
+                didSomething = true;
+                break;
+            }
         }
     }
+    while ( didSomething );
 }
 
-static void CopyTextToClipboard( const wxString& text )
-{
-    if ( wxTheClipboard->Open() )
-    {
-        // This data objects are held by the clipboard, 
-        // so do not delete them in the app.
-        wxTheClipboard->SetData( new wxTextDataObject(text) );
-        wxTheClipboard->Close();
-    }
-}
-
-void wxPropertyGrid::HandleKeyEvent(wxKeyEvent &event)
+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.
+    wxPGProperty* selected = GetSelection();
     int keycode = event.GetKeyCode();
+    bool editorFocused = IsEditorFocused();
 
     if ( keycode == WXK_TAB )
     {
-        SendNavigationKeyEvent( event.ShiftDown()?0:1 );
-        return;
-    }
-
-    // Ignore Alt and Control when they are down alone
-    if ( keycode == WXK_ALT ||
-         keycode == WXK_CONTROL )
-    {
-        event.Skip();
-        return;
-    }
-
-    int secondAction;
-    int action = KeyEventToActions(event, &secondAction);
-
-    if ( m_selected )
-    {
-
-        // Show dialog?
-        if ( ButtonTriggerKeyTest(event) )
-            return;
+        wxWindow* mainControl;
 
-        wxPGProperty* p = m_selected;
+        if ( HasInternalFlag(wxPG_FL_IN_MANAGER) )
+            mainControl = GetParent();
+        else
+            mainControl = this;
 
-        if ( action == wxPG_ACTION_COPY )
+        if ( !event.ShiftDown() )
         {
-            CopyTextToClipboard(p->GetDisplayedString());
+            if ( !editorFocused && m_wndEditor )
+            {
+                DoSelectProperty( selected, wxPG_SEL_FOCUS );
+            }
+            else
+            {
+                // Tab traversal workaround for platforms on which
+                // wxWindow::Navigate() may navigate into first child
+                // instead of next sibling. Does not work perfectly
+                // in every scenario (for instance, when property grid
+                // is either first or last control).
+            #if defined(__WXGTK__)
+                wxWindow* sibling = mainControl->GetNextSibling();
+                if ( sibling )
+                    sibling->SetFocusFromKbd();
+            #else
+                Navigate(wxNavigationKeyEvent::IsForward);
+            #endif
+            }
         }
         else
         {
-            // Travel and expand/collapse
-            int selectDir = -2;
-
-            if ( p->GetChildCount() &&
-                 !(p->m_flags & wxPG_PROP_DISABLED)
-               )
-            {
-                if ( action == wxPG_ACTION_COLLAPSE_PROPERTY || secondAction == wxPG_ACTION_COLLAPSE_PROPERTY )
-                {
-                    if ( (m_windowStyle & wxPG_HIDE_MARGIN) || Collapse(p) )
-                        keycode = 0;
-                }
-                else if ( action == wxPG_ACTION_EXPAND_PROPERTY || secondAction == wxPG_ACTION_EXPAND_PROPERTY )
-                {
-                    if ( (m_windowStyle & wxPG_HIDE_MARGIN) || Expand(p) )
-                        keycode = 0;
-                }
-            }
-
-            if ( keycode )
+            if ( editorFocused )
             {
-                if ( action == wxPG_ACTION_PREV_PROPERTY || secondAction == wxPG_ACTION_PREV_PROPERTY )
-                {
-                    selectDir = -1;
-                }
-                else if ( action == wxPG_ACTION_NEXT_PROPERTY || secondAction == wxPG_ACTION_NEXT_PROPERTY )
-                {
-                    selectDir = 1;
-                }
-                else
-                {
-                    event.Skip();
-                }
-
+                UnfocusEditor();
             }
-
-            if ( selectDir >= -1 )
+            else
             {
-                p = wxPropertyGridIterator::OneStep( m_pState, wxPG_ITERATE_VISIBLE, p, selectDir );
-                if ( p )
-                    DoSelectProperty(p);
+            #if defined(__WXGTK__)
+                wxWindow* sibling = mainControl->GetPrevSibling();
+                if ( sibling )
+                    sibling->SetFocusFromKbd();
+            #else
+                Navigate(wxNavigationKeyEvent::IsBackward);
+            #endif
             }
         }
-    }
-    else
-    {
-        // If nothing was selected, select the first item now
-        // (or navigate out of tab).
-        if ( action != wxPG_ACTION_CANCEL_EDIT && secondAction != wxPG_ACTION_CANCEL_EDIT )
-        {
-            wxPGProperty* p = wxPropertyGridInterface::GetFirst();
-            if ( p ) DoSelectProperty(p);
-        }
-    }
-}
 
-// -----------------------------------------------------------------------
-
-// Potentially handles a keyboard event for editor controls.
-// Returns false if event should *not* be skipped (on true it can
-// be optionally skipped).
-// Basicly, false means that SelectProperty was called (or was about
-// to be called, if canDestroy was false).
-bool wxPropertyGrid::HandleChildKey( wxKeyEvent& event )
-{
-    bool res = true;
+        return;
+    }
 
-    if ( !m_selected || !m_wndEditor )
+    // Ignore Alt and Control when they are down alone
+    if ( keycode == WXK_ALT ||
+         keycode == WXK_CONTROL )
     {
-        return true;
+        event.Skip();
+        return;
     }
 
-    int action = KeyEventToAction(event);
+    int secondAction;
+    int action = KeyEventToActions(event, &secondAction);
 
-    // Unfocus?
-    if ( action == wxPG_ACTION_CANCEL_EDIT )
+    if ( editorFocused && action == wxPG_ACTION_CANCEL_EDIT )
     {
         //
         // Esc cancels any changes
         if ( IsEditorsValueModified() )
         {
-            EditorsValueWasNotModified();
-
-            // Update the control as well
-            m_selected->GetEditorClass()->SetControlStringValue( m_selected,
-                                                                 m_wndEditor,
-                                                                 m_selected->GetDisplayedString() );
-        }
-
-        OnValidationFailureReset(m_selected);
-
-        res = false;
-
-        UnfocusEditor();
-    }
-    else if ( action == wxPG_ACTION_COPY )
-    {
-        // NB: There is some problem with getting native cut-copy-paste keys to go through
-        //     for embedded editor wxTextCtrl. This is why we emulate.
-        //
-        wxTextCtrl* tc = GetEditorTextCtrl();
-        if ( tc )
-        {
-            wxString sel = tc->GetStringSelection();
-            if ( sel.length() )
-                CopyTextToClipboard(sel);
-        }
-        else
-        {
-            CopyTextToClipboard(m_selected->GetDisplayedString());
-        }
-    }
-    else if ( action == wxPG_ACTION_CUT )
-    {
-        wxTextCtrl* tc = GetEditorTextCtrl();
-        if ( tc )
-        {
-            long from, to;
-            tc->GetSelection(&from, &to);
-            if ( from < to )
-            {
-                CopyTextToClipboard(tc->GetStringSelection());
-                tc->Remove(from, to);
-            }
-        }
-    }
-    else if ( action == wxPG_ACTION_PASTE )
-    {
-        wxTextCtrl* tc = GetEditorTextCtrl();
-        if ( tc )
-        {
-            if (wxTheClipboard->Open())
-            {
-                if (wxTheClipboard->IsSupported( wxDF_TEXT ))
-                {
-                    wxTextDataObject data;
-                    wxTheClipboard->GetData( data );
-                    long from, to;
-                    tc->GetSelection(&from, &to);
-                    if ( from < to )
-                    {
-                        tc->Remove(from, to);
-                        tc->WriteText(data.GetText());
-                    }
-                    else
-                    {
-                        tc->WriteText(data.GetText());
-                    }
-                }  
-                wxTheClipboard->Close();
-            }
-        }
-    }
-
-    return res;
-}
-
-// -----------------------------------------------------------------------
-
-void wxPropertyGrid::OnKey( wxKeyEvent &event )
-{
-
-    //
-    // Events to editor controls should get relayed here.
-    //
-    wxWindow* focused = wxWindow::FindFocus();
-
-    wxWindow* primaryCtrl = GetEditorControl();
-
-    if ( primaryCtrl &&
-         (focused==primaryCtrl
-          || m_editorFocused) )
-    {
-        // Child key must be processed here, since it can
-        // destroy the control which is referred by its own
-        // event handling.
-        HandleChildKey( event );
-    }
-    else
-        HandleKeyEvent( event );
-}
-
-// -----------------------------------------------------------------------
+            EditorsValueWasNotModified();
 
-void wxPropertyGrid::OnKeyUp(wxKeyEvent &event)
-{
-    m_keyComboConsumed = 0;
+            // Update the control as well
+            selected->GetEditorClass()->
+                SetControlStringValue( selected,
+                                       GetEditorControl(),
+                                       selected->GetDisplayedString() );
+        }
 
-    event.Skip();
-}
+        OnValidationFailureReset(selected);
 
-// -----------------------------------------------------------------------
+        UnfocusEditor();
+        return;
+    }
 
-void wxPropertyGrid::OnNavigationKey( wxNavigationKeyEvent& event )
-{
-    // Ignore events that occur very close to focus set
-    if ( m_iFlags & wxPG_FL_IGNORE_NEXT_NAVKEY )
+    // Except for TAB and ESC, handle child control events in child control
+    if ( fromChild )
     {
-        m_iFlags &= ~(wxPG_FL_IGNORE_NEXT_NAVKEY);
+        // Only propagate event if it had modifiers
+        if ( !event.HasModifiers() )
+        {
+            event.StopPropagation();
+        }
         event.Skip();
         return;
     }
 
-    wxPGProperty* next = (wxPGProperty*) NULL;
-
-    int dir = event.GetDirection()?1:-1;
+    bool wasHandled = false;
 
-    if ( m_selected )
+    if ( selected )
     {
-        if ( dir == 1 && (m_wndEditor || m_wndEditor2) )
-        {
-            wxWindow* focused = wxWindow::FindFocus();
+        // Show dialog?
+        if ( ButtonTriggerKeyTest(action, event) )
+            return;
 
-            wxWindow* wndToCheck = GetEditorControl();
+        wxPGProperty* p = selected;
 
-            // ODComboBox focus goes to its text ctrl, so we need to use it instead
-            if ( wndToCheck && wndToCheck->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)) )
-            {
-                wxTextCtrl* comboTextCtrl = ((wxOwnerDrawnComboBox*)wndToCheck)->GetTextCtrl();
-                if ( comboTextCtrl )
-                    wndToCheck = comboTextCtrl;
-            }
+        // Travel and expand/collapse
+        int selectDir = -2;
 
-            /*
-            // Because of problems navigating from wxButton, do not go to it.
-            if ( !wndToCheck )
+        if ( p->GetChildCount() )
+        {
+            if ( action == wxPG_ACTION_COLLAPSE_PROPERTY || secondAction == wxPG_ACTION_COLLAPSE_PROPERTY )
             {
-                // No primary, use secondary
-                wndToCheck = m_wndEditor2;
+                if ( (m_windowStyle & wxPG_HIDE_MARGIN) || Collapse(p) )
+                    wasHandled = true;
             }
-            // If it has editor button, focus to it after the primary editor.
-            // NB: Doesn't work since wxButton on wxMSW doesn't seem to propagate
-            //     key events (yes, I'm using wxWANTS_CHARS with it, and yes I
-            //     have somewhat debugged in window.cpp itself).
-            else if ( focused == wndToCheck &&
-                      m_wndEditor2 &&
-                      !(GetExtraStyle() & wxPG_EX_NO_TAB_TO_BUTTON) )
+            else if ( action == wxPG_ACTION_EXPAND_PROPERTY || secondAction == wxPG_ACTION_EXPAND_PROPERTY )
             {
-                wndToCheck = m_wndEditor2;
-                wxLogDebug(wxT("Exp1"));
+                if ( (m_windowStyle & wxPG_HIDE_MARGIN) || Expand(p) )
+                    wasHandled = true;
             }
-            */
+        }
 
-            if ( focused != wndToCheck &&
-                 wndToCheck )
+        if ( !wasHandled )
+        {
+            if ( action == wxPG_ACTION_PREV_PROPERTY || secondAction == wxPG_ACTION_PREV_PROPERTY )
             {
-                wndToCheck->SetFocus();
-
-                // Select all text in wxTextCtrl etc.
-                if ( m_wndEditor && wndToCheck == m_wndEditor )
-                    m_selected->GetEditorClass()->OnFocus(m_selected,wndToCheck);
-
-                m_editorFocused = 1;
-                next = m_selected;
+                selectDir = -1;
+            }
+            else if ( action == wxPG_ACTION_NEXT_PROPERTY || secondAction == wxPG_ACTION_NEXT_PROPERTY )
+            {
+                selectDir = 1;
             }
         }
 
-        if ( !next )
+        if ( selectDir >= -1 )
         {
-            next = wxPropertyGridIterator::OneStep(m_pState, wxPG_ITERATE_VISIBLE, m_selected, dir);
-
-            if ( next )
-            {
-                // This allows preventing NavigateOut to occur
-                DoSelectProperty( next, wxPG_SEL_FOCUS );
-            }
+            p = wxPropertyGridIterator::OneStep( m_pState, wxPG_ITERATE_VISIBLE, p, selectDir );
+            if ( p )
+                DoSelectProperty(p);
+            wasHandled = true;
+        }
+    }
+    else
+    {
+        // If nothing was selected, select the first item now
+        // (or navigate out of tab).
+        if ( action != wxPG_ACTION_CANCEL_EDIT && secondAction != wxPG_ACTION_CANCEL_EDIT )
+        {
+            wxPGProperty* p = wxPropertyGridInterface::GetFirst();
+            if ( p ) DoSelectProperty(p);
+            wasHandled = true;
         }
     }
 
-    if ( !next )
+    if ( !wasHandled )
         event.Skip();
 }
 
 // -----------------------------------------------------------------------
 
-bool wxPropertyGrid::ButtonTriggerKeyTest( wxKeyEvent &event )
+void wxPropertyGrid::OnKey( wxKeyEvent &event )
 {
-    int keycode = event.GetKeyCode();
-
-    // Does the keycode trigger button?
-    if ( keycode == m_pushButKeyCode &&
-         m_wndEditor2 &&
-         (!m_pushButKeyCodeNeedsAlt || event.AltDown()) &&
-         (!m_pushButKeyCodeNeedsCtrl || event.ControlDown()) )
+    // If there was editor open and focused, then this event should not
+    // really be processed here.
+    if ( IsEditorFocused() )
     {
-        m_keyComboConsumed = 1;
-
-        wxCommandEvent evt(wxEVT_COMMAND_BUTTON_CLICKED,m_wndEditor2->GetId());
-        GetEventHandler()->AddPendingEvent(evt);
-        return true;
+        // However, if event had modifiers, it is probably still best
+        // to skip it.
+        if ( event.HasModifiers() )
+            event.Skip();
+        else
+            event.StopPropagation();
+        return;
     }
 
-    return false;
+    HandleKeyEvent(event, false);
 }
 
 // -----------------------------------------------------------------------
 
-void wxPropertyGrid::OnChildKeyDown( wxKeyEvent &event )
+bool wxPropertyGrid::ButtonTriggerKeyTest( int action, wxKeyEvent& event )
 {
-    int keycode = event.GetKeyCode();
-
-    // Ignore Alt and Control when they are down alone
-    if ( keycode == WXK_ALT ||
-         keycode == WXK_CONTROL )
+    if ( action == -1 )
     {
-        event.Skip();
-        return;
+        int secondAction;
+        action = KeyEventToActions(event, &secondAction);
     }
 
-    if ( ButtonTriggerKeyTest(event) )
-        return;
-
-    if ( HandleChildKey(event) == true )
-        event.Skip();
+    // Does the keycode trigger button?
+    if ( action == wxPG_ACTION_PRESS_BUTTON &&
+         m_wndEditor2 )
+    {
+        wxCommandEvent evt(wxEVT_COMMAND_BUTTON_CLICKED, m_wndEditor2->GetId());
+        GetEventHandler()->AddPendingEvent(evt);
+        return true;
+    }
 
-    GetEventHandler()->AddPendingEvent(event);
+    return false;
 }
 
-void wxPropertyGrid::OnChildKeyUp( wxKeyEvent &event )
-{
-    m_keyComboConsumed = 0;
-
-    GetEventHandler()->AddPendingEvent(event);
+// -----------------------------------------------------------------------
 
-    event.Skip();
+void wxPropertyGrid::OnChildKeyDown( wxKeyEvent &event )
+{
+    HandleKeyEvent(event, true);
 }
 
 // -----------------------------------------------------------------------
@@ -5349,6 +5506,26 @@ void wxPropertyGrid::OnIdle( wxIdleEvent& WXUNUSED(event) )
 
     if ( newFocused != m_curFocused )
         HandleFocusChange( newFocused );
+
+    //
+    // Check if top-level parent has changed
+    if ( GetExtraStyle() & wxPG_EX_ENABLE_TLP_TRACKING )
+    {
+        wxWindow* tlp = ::wxGetTopLevelParent(this);
+        if ( tlp != m_tlp )
+            OnTLPChanging(tlp);
+    }
+}
+
+bool wxPropertyGrid::IsEditorFocused() const
+{
+    wxWindow* focus = wxWindow::FindFocus();
+
+    if ( focus == m_wndEditor || focus == m_wndEditor2 ||
+         focus == GetEditorControl() )
+         return true;
+
+    return false;
 }
 
 // Called by focus event handlers. newFocused is the window that becomes focused.
@@ -5378,13 +5555,8 @@ void wxPropertyGrid::HandleFocusChange( wxWindow* newFocused )
     if ( (m_iFlags & wxPG_FL_FOCUSED) !=
          (oldFlags & wxPG_FL_FOCUSED) )
     {
-        // On each focus kill, mark the next nav key event
-        // to be ignored (can't do on set focus since the
-        // event would occur before it).
         if ( !(m_iFlags & wxPG_FL_FOCUSED) )
         {
-            m_iFlags |= wxPG_FL_IGNORE_NEXT_NAVKEY;
-
             // Need to store changed value
             CommitChangesFromEditor();
         }
@@ -5417,13 +5589,12 @@ void wxPropertyGrid::HandleFocusChange( wxWindow* newFocused )
 
             }
             */
-
-            m_iFlags &= ~(wxPG_FL_IGNORE_NEXT_NAVKEY);
         }
 
         // Redraw selected
-        if ( m_selected && (m_iFlags & wxPG_FL_INITIALIZED) )
-            DrawItem( m_selected );
+        wxPGProperty* selected = GetSelection();
+        if ( selected && (m_iFlags & wxPG_FL_INITIALIZED) )
+            DrawItem( selected );
     }
 }
 
@@ -5444,11 +5615,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();
 }
 
 // -----------------------------------------------------------------------
@@ -5475,19 +5642,29 @@ 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);
 
+    if ( vt_it != wxPGGlobalVars->m_mapEditorClasses.end() )
+    {
+        // If this name was already used, try class name.
+        name = editorClass->GetClassInfo()->GetClassName();
+        vt_it = wxPGGlobalVars->m_mapEditorClasses.find(name);
+    }
+
     wxCHECK_MSG( vt_it == wxPGGlobalVars->m_mapEditorClasses.end(),
                  (wxPGEditor*) vt_it->second,
                  "Editor with given name was already registered" );
@@ -5497,6 +5674,14 @@ wxPGEditor* wxPropertyGrid::RegisterEditorClass( wxPGEditor* editorClass,
     return editorClass;
 }
 
+// Use this in RegisterDefaultEditors.
+#define wxPGRegisterDefaultEditorClass(EDITOR) \
+    if ( wxPGEditor_##EDITOR == NULL ) \
+    { \
+        wxPGEditor_##EDITOR = wxPropertyGrid::RegisterEditorClass( \
+            new wxPG##EDITOR##Editor, true ); \
+    }
+
 // Registers all default editor classes
 void wxPropertyGrid::RegisterDefaultEditors()
 {
@@ -5562,7 +5747,7 @@ bool wxPGStringTokenizer::HasMoreTokens()
                 }
                 else
                 {
-                    i++;
+                    ++i;
                     m_curPos = i;
                     return true;
                 }
@@ -5574,7 +5759,7 @@ bool wxPGStringTokenizer::HasMoreTokens()
                 prev_a = wxT('\0');
             }
         }
-        i++;
+        ++i;
     }
 
     m_curPos = str.end();
@@ -5599,19 +5784,12 @@ wxPGChoiceEntry::wxPGChoiceEntry()
 {
 }
 
-wxPGChoiceEntry::wxPGChoiceEntry( const wxPGChoiceEntry& entry )
-    : wxPGCell( entry.GetText(), entry.GetBitmap(),
-        entry.GetFgCol(), entry.GetBgCol() ), m_value(entry.GetValue())
-{
-}
-
 // -----------------------------------------------------------------------
 // wxPGChoicesData
 // -----------------------------------------------------------------------
 
 wxPGChoicesData::wxPGChoicesData()
 {
-    m_refCount = 1;
 }
 
 wxPGChoicesData::~wxPGChoicesData()
@@ -5621,13 +5799,6 @@ wxPGChoicesData::~wxPGChoicesData()
 
 void wxPGChoicesData::Clear()
 {
-    unsigned int i;
-
-    for ( i=0; i<m_items.size(); i++ )
-    {
-        delete Item(i);
-    }
-
     m_items.clear();
 }
 
@@ -5635,276 +5806,32 @@ void wxPGChoicesData::CopyDataFrom( wxPGChoicesData* data )
 {
     wxASSERT( m_items.size() == 0 );
 
-    unsigned int i;
-
-    for ( i=0; i<data->GetCount(); i++ )
-        m_items.push_back( new wxPGChoiceEntry(*data->Item(i)) );
-}
-
-// -----------------------------------------------------------------------
-// wxPGChoices
-// -----------------------------------------------------------------------
-
-wxPGChoiceEntry& wxPGChoices::Add( const wxString& label, int value )
-{
-    EnsureData();
-
-    wxPGChoiceEntry* p = new wxPGChoiceEntry(label, value);
-    m_data->Insert( -1, p );
-    return *p;
-}
-
-// -----------------------------------------------------------------------
-
-wxPGChoiceEntry& wxPGChoices::Add( const wxString& label, const wxBitmap& bitmap, int value )
-{
-    EnsureData();
-
-    wxPGChoiceEntry* p = new wxPGChoiceEntry(label, value);
-    p->SetBitmap(bitmap);
-    m_data->Insert( -1, p );
-    return *p;
-}
-
-// -----------------------------------------------------------------------
-
-wxPGChoiceEntry& wxPGChoices::Insert( const wxPGChoiceEntry& entry, int index )
-{
-    EnsureData();
-
-    wxPGChoiceEntry* p = new wxPGChoiceEntry(entry);
-    m_data->Insert(index, p);
-    return *p;
-}
-
-// -----------------------------------------------------------------------
-
-wxPGChoiceEntry& wxPGChoices::Insert( const wxString& label, int index, int value )
-{
-    EnsureData();
-
-    wxPGChoiceEntry* p = new wxPGChoiceEntry(label, value);
-    m_data->Insert( index, p );
-    return *p;
-}
-
-// -----------------------------------------------------------------------
-
-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* p = new wxPGChoiceEntry(label, value);
-    m_data->Insert( index, p );
-    return *p;
-}
-
-// -----------------------------------------------------------------------
-
-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 = wxPG_INVALID_VALUE;
-        if ( values )
-            value = values[i];
-        m_data->Insert( -1, new wxPGChoiceEntry(labels[i], value) );
-    }
-}
-
-// -----------------------------------------------------------------------
-
-void wxPGChoices::Add( const wxArrayString& arr, const ValArrItem* values )
-{
-    EnsureData();
-
-    unsigned int i;
-    unsigned int itemcount = arr.size();
-
-    for ( i = 0; i < itemcount; i++ )
-    {
-        int value = wxPG_INVALID_VALUE;
-        if ( values )
-            value = values[i];
-        m_data->Insert( -1, new wxPGChoiceEntry(arr[i], value) );
-    }
-}
-
-// -----------------------------------------------------------------------
-
-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 = wxPG_INVALID_VALUE;
-        if ( &arrint && arrint.size() )
-            value = arrint[i];
-        m_data->Insert( -1, new wxPGChoiceEntry(arr[i], value) );
-    }
-}
-
-// -----------------------------------------------------------------------
-
-void wxPGChoices::RemoveAt(size_t nIndex, size_t count)
-{
-    wxASSERT( m_data->m_refCount != 0xFFFFFFF );
-    unsigned int i;
-    for ( i=nIndex; i<(nIndex+count); i++)
-        delete m_data->Item(i);
-    m_data->m_items.erase(m_data->m_items.begin()+nIndex,
-                          m_data->m_items.begin()+nIndex+count-1);
-}
-
-// -----------------------------------------------------------------------
-
-int wxPGChoices::Index( const wxString& str ) const
-{
-    if ( IsOk() )
-    {
-        unsigned int i;
-        for ( i=0; i< m_data->GetCount(); i++ )
-        {
-            if ( m_data->Item(i)->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++ )
-        {
-            if ( m_data->Item(i)->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;
-}
-
-// -----------------------------------------------------------------------
-
-bool wxPGChoices::HasValues() const
-{
-    return true;
-}
-
-// -----------------------------------------------------------------------
-
-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;
+    m_items = data->m_items;
 }
 
-// -----------------------------------------------------------------------
-
-wxArrayInt wxPGChoices::GetIndicesForStrings( const wxArrayString& strings, 
-                                              wxArrayString* unmatched ) const
+wxPGChoiceEntry& wxPGChoicesData::Insert( int index,
+                                          const wxPGChoiceEntry& item )
 {
-    wxArrayInt arr;
-
-    if ( IsOk() )
+    wxVector<wxPGChoiceEntry>::iterator it;
+    if ( index == -1 )
     {
-        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);
-        }
+        it = m_items.end();
+        index = (int) m_items.size();
     }
-
-    return arr;
-}
-
-// -----------------------------------------------------------------------
-
-void wxPGChoices::AssignData( wxPGChoicesData* data )
-{
-    Free();
-
-    if ( data != wxPGChoicesEmptyData )
+    else
     {
-        m_data = data;
-        data->m_refCount++;
+        it = m_items.begin() + index;
     }
-}
 
-// -----------------------------------------------------------------------
+    m_items.insert(it, item);
 
-void wxPGChoices::Init()
-{
-    m_data = wxPGChoicesEmptyData;
-}
+    wxPGChoiceEntry& ownEntry = m_items[index];
 
-// -----------------------------------------------------------------------
+    // Need to fix value?
+    if ( ownEntry.GetValue() == wxPG_INVALID_VALUE )
+        ownEntry.SetValue(index);
 
-void wxPGChoices::Free()
-{
-    if ( m_data != wxPGChoicesEmptyData )
-    {
-        m_data->DecRef();
-        m_data = wxPGChoicesEmptyData;
-    }
+    return ownEntry;
 }
 
 // -----------------------------------------------------------------------
@@ -5914,22 +5841,24 @@ 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 );
+wxDEFINE_EVENT( wxEVT_PG_LABEL_EDIT_BEGIN, wxPropertyGridEvent );
+wxDEFINE_EVENT( wxEVT_PG_LABEL_EDIT_ENDING, wxPropertyGridEvent );
 
 // -----------------------------------------------------------------------
 
 void wxPropertyGridEvent::Init()
 {
     m_validationInfo = NULL;
+    m_column = 1;
     m_canVeto = false;
     m_wasVetoed = false;
 }
@@ -5951,6 +5880,7 @@ wxPropertyGridEvent::wxPropertyGridEvent(const wxPropertyGridEvent& event)
     m_eventType = event.GetEventType();
     m_eventObject = event.m_eventObject;
     m_pg = event.m_pg;
+    OnPropertyGridSet();
     m_property = event.m_property;
     m_validationInfo = event.m_validationInfo;
     m_canVeto = event.m_canVeto;
@@ -5959,8 +5889,40 @@ wxPropertyGridEvent::wxPropertyGridEvent(const wxPropertyGridEvent& event)
 
 // -----------------------------------------------------------------------
 
+void wxPropertyGridEvent::OnPropertyGridSet()
+{
+    if ( !m_pg )
+        return;
+
+#if wxUSE_THREADS
+    wxCriticalSectionLocker(wxPGGlobalVars->m_critSect);
+#endif
+    m_pg->m_liveEvents.push_back(this);
+}
+
+// -----------------------------------------------------------------------
+
 wxPropertyGridEvent::~wxPropertyGridEvent()
 {
+    if ( m_pg )
+    {
+    #if wxUSE_THREADS
+        wxCriticalSectionLocker(wxPGGlobalVars->m_critSect);
+    #endif
+
+        // Use iterate from the back since it is more likely that the event
+        // being desroyed is at the end of the array.
+        wxVector<wxPropertyGridEvent*>& liveEvents = m_pg->m_liveEvents;
+
+        for ( int i = liveEvents.size()-1; i >= 0; i-- )
+        {
+            if ( liveEvents[i] == this )
+            {
+                liveEvents.erase(liveEvents.begin() + i);
+                break;
+            }
+        }
+    }
 }
 
 // -----------------------------------------------------------------------
@@ -6053,7 +6015,8 @@ wxPGProperty* wxPropertyGridPopulator::Add( const wxString& propClass,
     m_state->DoInsert(parent, -1, property);
 
     if ( propValue )
-        property->SetValueFromString( *propValue, wxPG_FULL_VALUE );
+        property->SetValueFromString( *propValue, wxPG_FULL_VALUE|
+                                                  wxPG_PROGRAMMATIC_VALUE );
 
     return property;
 }
@@ -6106,7 +6069,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;