]> git.saurik.com Git - wxWidgets.git/blobdiff - src/propgrid/propgrid.cpp
wxPGProperty::GenerateComposedValue() -> protected DoGenerateComposedValue(), added...
[wxWidgets.git] / src / propgrid / propgrid.cpp
index cdafad48f02e48eef792334ca4a1735d90e1dee7..f512a6e82b21eb1cebd819271a962ca1e67474ec 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
 /////////////////////////////////////////////////////////////////////////////
@@ -40,7 +40,6 @@
     #include "wx/stattext.h"
     #include "wx/scrolwin.h"
     #include "wx/dirdlg.h"
-    #include "wx/layout.h"
     #include "wx/sizer.h"
     #include "wx/textdlg.h"
     #include "wx/filedlg.h"
 // 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>
+#include "wx/clipbrd.h"
+#include "wx/dataobj.h"
 
 #ifdef __WXMSW__
-    #include <wx/msw/private.h>
+    #include "wx/msw/private.h"
 #endif
 
-#include <typeinfo>
-
 // Two pics for the expand / collapse buttons.
 // Files are not supplied with this project (since it is
 // recommended to use either custom or native rendering).
@@ -141,18 +138,9 @@ const wxChar *wxPropertyGridNameStr = wxT("wxPropertyGrid");
 
 // -----------------------------------------------------------------------
 // Statics in one class for easy destruction.
-// NB: We prefer to use wxModule, as it offers more consistent behavior
-//     across platforms. However, for those rare problem situations, we
-//     also need to offer option to use simpler approach.
 // -----------------------------------------------------------------------
 
-#ifndef wxPG_USE_WXMODULE
-    #define wxPG_USE_WXMODULE 1
-#endif
-
-#if wxPG_USE_WXMODULE
-
-#include <wx/module.h>
+#include "wx/module.h"
 
 class wxPGGlobalVarsClassManager : public wxModule
 {
@@ -165,19 +153,6 @@ public:
 
 IMPLEMENT_DYNAMIC_CLASS(wxPGGlobalVarsClassManager, wxModule)
 
-#else // !wxPG_USE_WXMODULE
-
-class wxPGGlobalVarsClassManager
-{
-public:
-    wxPGGlobalVarsClassManager() {}
-    ~wxPGGlobalVarsClassManager() { delete wxPGGlobalVars; }
-};
-
-static wxPGGlobalVarsClassManager gs_pgGlobalVarsClassManager;
-
-#endif
-
 
 wxPGGlobalVarsClass* wxPGGlobalVars = (wxPGGlobalVarsClass*) NULL;
 
@@ -252,6 +227,10 @@ wxPGGlobalVarsClass::~wxPGGlobalVarsClass()
     delete wxPGProperty::sm_wxPG_LABEL;
 }
 
+void wxPropertyGridInitGlobalsIfNeeded()
+{
+}
+
 // -----------------------------------------------------------------------
 // wxPGBrush
 // -----------------------------------------------------------------------
@@ -435,19 +414,21 @@ protected:
         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()
+    DECLARE_ABSTRACT_CLASS(wxPGCanvas)
 };
 
 
+IMPLEMENT_ABSTRACT_CLASS(wxPGCanvas,wxPanel)
+
 BEGIN_EVENT_TABLE(wxPGCanvas, wxPanel)
     EVT_MOTION(wxPGCanvas::OnMouseMove)
     EVT_PAINT(wxPGCanvas::OnPaint)
@@ -458,7 +439,6 @@ BEGIN_EVENT_TABLE(wxPGCanvas, wxPanel)
     EVT_KEY_DOWN(wxPGCanvas::OnKey)
     EVT_KEY_UP(wxPGCanvas::OnKeyUp)
     EVT_CHAR(wxPGCanvas::OnKey)
-    EVT_NAVIGATION_KEY(wxPGCanvas::OnNavigationKey)
 END_EVENT_TABLE()
 
 
@@ -502,7 +482,6 @@ BEGIN_EVENT_TABLE(wxPropertyGrid, wxScrolledWindow)
   EVT_CHILD_FOCUS(wxPropertyGrid::OnChildFocusEvent)
   EVT_SET_FOCUS(wxPropertyGrid::OnFocusEvent)
   EVT_KILL_FOCUS(wxPropertyGrid::OnFocusEvent)
-  EVT_TEXT_ENTER(wxPG_SUBID1,wxPropertyGrid::OnCustomEditorEvent)
   EVT_SYS_COLOUR_CHANGED(wxPropertyGrid::OnSysColourChanged)
 END_EVENT_TABLE()
 
@@ -571,14 +550,9 @@ bool wxPropertyGrid::Create( wxWindow *parent,
 //
 void wxPropertyGrid::Init1()
 {
-#if !wxPG_USE_WXMODULE
-    if ( !wxPGGlobalVars )
-        wxPGGlobalVars = new wxPGGlobalVarsClass();
-#endif
-
     // Register editor classes, if necessary.
     if ( wxPGGlobalVars->m_mapEditorClasses.empty() )
-        RegisterDefaultEditors();
+        wxPropertyGrid::RegisterDefaultEditors();
 
     m_iFlags = 0;
     m_pState = (wxPropertyGridPageState*) NULL;
@@ -605,12 +579,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;
@@ -621,8 +591,6 @@ void wxPropertyGrid::Init1()
     m_doubleBuffer = (wxBitmap*) NULL;
 #endif
 
-    m_windowsToDelete = NULL;
-
 #ifndef wxPG_ICON_WIDTH
        m_expandbmp = NULL;
        m_collbmp = NULL;
@@ -641,10 +609,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;
 
@@ -780,8 +744,6 @@ wxPropertyGrid::~wxPropertyGrid()
         delete m_doubleBuffer;
 #endif
 
-    delete m_windowsToDelete;
-
     //m_selected = (wxPGProperty*) NULL;
 
     if ( m_iFlags & wxPG_FL_CREATEDSTATE )
@@ -1206,7 +1168,8 @@ bool wxPropertyGrid::SetFont( const wxFont& font )
     // TODO: Following code is disabled with wxMac because
     //   it is reported to fail. I (JMS) cannot debug it
     //   personally right now.
-#if !defined(__WXMAC__)
+    // CS: should be fixed now, leaving old code in just in case, TODO: REMOVE
+#if 1 // !defined(__WXMAC__)
     bool res = wxScrolledWindow::SetFont( font );
     if ( res )
     {
@@ -1507,7 +1470,8 @@ void wxPropertyGrid::DoSetPropertyValueUnspecified( wxPGProperty* p )
     DrawItemAndChildren(p);
 
     wxPGProperty* parent = p->GetParent();
-    while ( (parent->GetFlags() & wxPG_PROP_PARENTAL_FLAGS) == wxPG_PROP_MISC_PARENT )
+    while ( parent &&
+            (parent->GetFlags() & wxPG_PROP_PARENTAL_FLAGS) == wxPG_PROP_MISC_PARENT )
     {
         DrawItem(parent);
         parent = parent->GetParent();
@@ -1518,18 +1482,6 @@ void wxPropertyGrid::DoSetPropertyValueUnspecified( wxPGProperty* p )
 // wxPropertyGrid property operations
 // -----------------------------------------------------------------------
 
-void wxPropertyGrid::DoSetPropertyName( wxPGProperty* p, const wxString& newname )
-{
-    wxCHECK_RET( p, wxT("invalid property id") );
-
-    if ( p->GetBaseName().Len() ) m_pState->m_dictName.erase( p->GetBaseName() );
-    if ( newname.Len() ) m_pState->m_dictName[newname] = (void*) p;
-
-    p->DoSetName(newname);
-}
-
-// -----------------------------------------------------------------------
-
 bool wxPropertyGrid::EnsureVisible( wxPGPropArg id )
 {
     wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
@@ -2679,24 +2631,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
 // -----------------------------------------------------------------------
@@ -2792,7 +2726,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.
@@ -2861,33 +2796,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 )
+        // 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) )
         {
-            evtChangingProperty->AdaptListToValue( bcpPendingList, &evtChangingValue );
-        }
-        else
-        {
-            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 )
+        if ( evtChangingProperty->HasFlag(wxPG_PROP_COMPOSED_VALUE) )
         {
-            wxASSERT( m_wndEditor->IsKindOf(CLASSINFO(wxTextCtrl)) );
-            evtChangingValue = ((wxTextCtrl*)m_wndEditor)->GetValue();
-        }
-        else
-        {
-            wxLogDebug(wxT("WARNING: wxEVT_PG_CHANGING is about to happen with old value."));
+            if ( changedProperty == m_selected )
+            {
+                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."));
+            }
         }
     }
 
@@ -2909,9 +2848,20 @@ 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, 0 ) )
+            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;
 }
@@ -3149,50 +3099,33 @@ bool wxPropertyGrid::ChangePropertyValue( wxPGPropArg id, wxVariant newValue )
 
 // -----------------------------------------------------------------------
 
-// Runs wxValidator for the selected property
-bool wxPropertyGrid::DoEditorValidate()
+wxVariant wxPropertyGrid::GetUncommittedPropertyValue()
 {
-#if wxUSE_VALIDATORS
-    // With traditional validator style, we dont need to more
-    if ( !(GetExtraStyle() & wxPG_EX_LEGACY_VALIDATORS) )
-        return true;
+    wxPGProperty* prop = GetSelectedProperty();
 
-    if ( m_iFlags & wxPG_FL_VALIDATION_FAILED )
-    {
-        return false;
-    }
+    if ( !prop )
+        return wxNullVariant;
 
-    wxWindow* wnd = GetEditorControl();
+    wxTextCtrl* tc = GetEditorTextCtrl();
+    wxVariant value = prop->GetValue();
 
-    wxValidator* validator = m_selected->GetValidator();
-    if ( validator && wnd )
-    {
-        // Use TextCtrl of ODComboBox instead
-        if ( wnd->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)) )
-        {
-            wnd = ((wxOwnerDrawnComboBox*)wnd)->GetTextCtrl();
+    if ( !tc || !IsEditorsValueModified() )
+        return value;
 
-            if ( !wnd )
-                return true;
-        }
+    if ( !prop->StringToValue(value, tc->GetValue()) )
+        return value;
 
-        validator->SetWindow(wnd);
+    if ( !PerformValidation(prop, value, IsStandaloneValidation) )
+        return prop->GetValue();
 
-        // Instead setting the flag after the failure, we set
-        // it before checking and then clear afterwards if things
-        // went fine. This trick is necessary since focus events
-        // may be triggered while in Validate.
-        m_iFlags |= wxPG_FL_VALIDATION_FAILED;
-        if ( !validator->Validate(this) )
-        {
-            // If you dpm't want to display message multiple times per change,
-            // comment the following line.
-            m_iFlags &= ~(wxPG_FL_VALIDATION_FAILED);
-            return false;
-        }
-        m_iFlags &= ~(wxPG_FL_VALIDATION_FAILED);
-    }
-#endif
+    return value;
+}
+
+// -----------------------------------------------------------------------
+
+// Runs wxValidator for the selected property
+bool wxPropertyGrid::DoEditorValidate()
+{
     return true;
 }
 
@@ -3224,7 +3157,6 @@ void wxPropertyGrid::OnCustomEditorEvent( wxCommandEvent &event )
 {
     wxPGProperty* selected = m_selected;
 
-    //
     // Somehow, event is handled after property has been deselected.
     // Possibly, but very rare.
     if ( !selected )
@@ -3282,22 +3214,25 @@ void wxPropertyGrid::OnCustomEditorEvent( wxCommandEvent &event )
         }
     }
 
-    if ( wnd && !buttonWasHandled )
+    if ( !buttonWasHandled )
     {
-        // First call editor class' event handler.
-        const wxPGEditor* editor = selected->GetEditorClass();
-
-        if ( editor->OnEvent( this, selected, wnd, event ) )
+        if ( wnd )
         {
-            // If changes, validate them
-            if ( DoEditorValidate() )
-            {
-                if ( editor->GetValueFromControl( pendingValue, m_selected, wnd ) )
-                    valueIsPending = true;
-            }
-            else
+            // First call editor class' event handler.
+            const wxPGEditor* editor = selected->GetEditorClass();
+
+            if ( editor->OnEvent( this, selected, wnd, event ) )
             {
-                validationFailure = true;
+                // If changes, validate them
+                if ( DoEditorValidate() )
+                {
+                    if ( editor->GetValueFromControl( pendingValue, m_selected, wnd ) )
+                        valueIsPending = true;
+                }
+                else
+                {
+                    validationFailure = true;
+                }
             }
         }
 
@@ -3320,7 +3255,7 @@ void wxPropertyGrid::OnCustomEditorEvent( wxCommandEvent &event )
         if ( !PerformValidation(m_selected, pendingValue) )
             validationFailure = true;
 
-    if ( validationFailure )
+    if ( validationFailure)
     {
         OnValidationFailure(selected, pendingValue);
     }
@@ -3330,10 +3265,24 @@ 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 )
+        {
+            SetFocusOnCanvas();
+        }
     }
     else
     {
         // 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 )
@@ -3471,52 +3420,70 @@ void wxPropertyGrid::CustomSetCursor( int type, bool override )
 // wxPropertyGrid property selection
 // -----------------------------------------------------------------------
 
-#define CONNECT_CHILD(EVT,FUNCTYPE,FUNC) \
-    wnd->Connect(id, EVT, \
-        (wxObjectEventFunction) (wxEventFunction)  \
-        FUNCTYPE (&wxPropertyGrid::FUNC), \
-        NULL, this );
-
 // Setups event handling for child control
-void wxPropertyGrid::SetupEventHandling( wxWindow* argWnd, int id )
+void wxPropertyGrid::SetupChildEventHandling( wxWindow* argWnd )
 {
-    wxWindow* wnd = argWnd;
+    wxWindowID id = argWnd->GetId();
 
     if ( argWnd == m_wndEditor )
     {
-        CONNECT_CHILD(wxEVT_MOTION,(wxMouseEventFunction),OnMouseMoveChild)
-        CONNECT_CHILD(wxEVT_LEFT_UP,(wxMouseEventFunction),OnMouseUpChild)
-        CONNECT_CHILD(wxEVT_LEFT_DOWN,(wxMouseEventFunction),OnMouseClickChild)
-        CONNECT_CHILD(wxEVT_RIGHT_UP,(wxMouseEventFunction),OnMouseRightClickChild)
-        CONNECT_CHILD(wxEVT_ENTER_WINDOW,(wxMouseEventFunction),OnMouseEntry)
-        CONNECT_CHILD(wxEVT_LEAVE_WINDOW,(wxMouseEventFunction),OnMouseEntry)
+        argWnd->Connect(id, wxEVT_MOTION,
+            wxMouseEventHandler(wxPropertyGrid::OnMouseMoveChild),
+            NULL, this);
+        argWnd->Connect(id, wxEVT_LEFT_UP,
+            wxMouseEventHandler(wxPropertyGrid::OnMouseUpChild),
+            NULL, this);
+        argWnd->Connect(id, wxEVT_LEFT_DOWN,
+            wxMouseEventHandler(wxPropertyGrid::OnMouseClickChild),
+            NULL, this);
+        argWnd->Connect(id, wxEVT_RIGHT_UP,
+            wxMouseEventHandler(wxPropertyGrid::OnMouseRightClickChild),
+            NULL, this);
+        argWnd->Connect(id, wxEVT_ENTER_WINDOW,
+            wxMouseEventHandler(wxPropertyGrid::OnMouseEntry),
+            NULL, this);
+        argWnd->Connect(id, wxEVT_LEAVE_WINDOW,
+            wxMouseEventHandler(wxPropertyGrid::OnMouseEntry),
+            NULL, this);
+        argWnd->Connect(id, wxEVT_KEY_DOWN,
+            wxCharEventHandler(wxPropertyGrid::OnChildKeyDown),
+            NULL, this);
     }
-    else
-    {
-        CONNECT_CHILD(wxEVT_NAVIGATION_KEY,(wxNavigationKeyEventFunction),OnNavigationKey)
-    }
-    CONNECT_CHILD(wxEVT_KEY_DOWN,(wxCharEventFunction),OnChildKeyDown)
-    CONNECT_CHILD(wxEVT_KEY_UP,(wxCharEventFunction),OnChildKeyUp)
-    CONNECT_CHILD(wxEVT_KILL_FOCUS,(wxFocusEventFunction),OnFocusEvent)
 }
 
 void wxPropertyGrid::FreeEditors()
 {
-    // Do not free editors immediately if processing events
-    if ( !m_windowsToDelete )
-        m_windowsToDelete = new wxArrayPtrVoid;
+    //
+    // 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);
         m_wndEditor2->Hide();
+        wxPendingDelete.Append( m_wndEditor2 );
         m_wndEditor2 = (wxWindow*) NULL;
     }
 
     if ( m_wndEditor )
     {
-        m_windowsToDelete->push_back(m_wndEditor);
         m_wndEditor->Hide();
+        wxPendingDelete.Append( m_wndEditor );
         m_wndEditor = (wxWindow*) NULL;
     }
 }
@@ -3541,25 +3508,24 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags )
 
     wxPGProperty* prev = m_selected;
 
-    //
-    // Delete windows pending for deletion
-    if ( m_windowsToDelete && !m_inDoPropertyChanged && m_windowsToDelete->size() )
-    {
-        unsigned int i;
-
-        for ( i=0; i<m_windowsToDelete->size(); i++ )
-            delete ((wxWindow*)((*m_windowsToDelete)[i]));
-
-        m_windowsToDelete->clear();
-    }
-
     if ( !m_pState )
     {
         m_inDoSelectProperty = 0;
         return false;
     }
 
-    //
+/*
+    if (m_selected)
+        wxPrintf( "Selected %s\n", m_selected->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 )
     {
@@ -3691,10 +3657,15 @@ 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 )
@@ -3704,12 +3675,9 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags )
 
                     // Set validator, if any
                 #if wxUSE_VALIDATORS
-                    if ( !(GetExtraStyle() & wxPG_EX_LEGACY_VALIDATORS) )
-                    {
-                        wxValidator* validator = p->GetValidator();
-                        if ( validator )
-                            m_wndEditor->SetValidator(*validator);
-                    }
+                    wxValidator* validator = p->GetValidator();
+                    if ( validator )
+                        primaryCtrl->SetValidator(*validator);
                 #endif
 
                     if ( m_wndEditor->GetSize().y > (m_lineHeight+6) )
@@ -3724,10 +3692,10 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags )
                     // Fix TextCtrl indentation
                 #if defined(__WXMSW__) && !defined(__WXWINCE__)
                     wxTextCtrl* tc = NULL;
-                    if ( m_wndEditor->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)) )
-                        tc = ((wxOwnerDrawnComboBox*)m_wndEditor)->GetTextCtrl();
+                    if ( primaryCtrl->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)) )
+                        tc = ((wxOwnerDrawnComboBox*)primaryCtrl)->GetTextCtrl();
                     else
-                        tc = wxDynamicCast(m_wndEditor, wxTextCtrl);
+                        tc = wxDynamicCast(primaryCtrl, wxTextCtrl);
                     if ( tc )
                         ::SendMessage(GetHwndOf(tc), EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(0, 0));
                 #endif
@@ -3753,8 +3721,7 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags )
                     m_wndEditor->Move( goodPos );
                 #endif
 
-                    wxWindow* primaryCtrl = GetEditorControl();
-                    SetupEventHandling(primaryCtrl, wxPG_SUBID1);
+                    SetupChildEventHandling(primaryCtrl);
 
                     // Focus and select all (wxTextCtrl, wxComboBox etc)
                     if ( flags & wxPG_SEL_FOCUS )
@@ -3794,7 +3761,7 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags )
                 #endif
                     m_wndEditor2->Show();
 
-                    SetupEventHandling(m_wndEditor2,wxPG_SUBID2);
+                    SetupChildEventHandling(m_wndEditor2);
 
                     // If no primary editor, focus to button to allow
                     // it to interprete ENTER etc.
@@ -4190,6 +4157,12 @@ void wxPropertyGrid::SetVirtualWidth( int width )
     m_pState->SetVirtualWidth( width );
 }
 
+void wxPropertyGrid::SetFocusOnCanvas()
+{
+    m_canvas->SetFocusIgnoringChildren();
+    m_editorFocused = 0;
+}
+
 // -----------------------------------------------------------------------
 // wxPropertyGrid mouse event handling
 // -----------------------------------------------------------------------
@@ -4709,13 +4682,13 @@ 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;
@@ -4864,8 +4837,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();
@@ -4934,17 +4905,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
@@ -5005,17 +4965,6 @@ void wxPropertyGrid::ClearActionTriggers( int action )
     }
 }
 
-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)
 {
     //
@@ -5031,7 +4980,8 @@ void wxPropertyGrid::HandleKeyEvent(wxKeyEvent &event)
 
     if ( keycode == WXK_TAB )
     {
-        SendNavigationKeyEvent( event.ShiftDown()?0:1 );
+        if (m_selected)
+            DoSelectProperty( m_selected, wxPG_SEL_FOCUS );
         return;
     }
 
@@ -5050,59 +5000,52 @@ void wxPropertyGrid::HandleKeyEvent(wxKeyEvent &event)
     {
 
         // Show dialog?
-        if ( ButtonTriggerKeyTest(event) )
+        if ( ButtonTriggerKeyTest(action, event) )
             return;
 
         wxPGProperty* p = m_selected;
 
-        if ( action == wxPG_ACTION_COPY )
+        // Travel and expand/collapse
+        int selectDir = -2;
+
+        if ( p->GetChildCount() &&
+             !(p->m_flags & wxPG_PROP_DISABLED)
+           )
         {
-            CopyTextToClipboard(p->GetDisplayedString());
+            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;
+            }
         }
-        else
-        {
-            // Travel and expand/collapse
-            int selectDir = -2;
 
-            if ( p->GetChildCount() &&
-                 !(p->m_flags & wxPG_PROP_DISABLED)
-               )
+        if ( keycode )
+        {
+            if ( action == wxPG_ACTION_PREV_PROPERTY || secondAction == wxPG_ACTION_PREV_PROPERTY )
             {
-                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;
-                }
+                selectDir = -1;
             }
-
-            if ( keycode )
+            else if ( action == wxPG_ACTION_NEXT_PROPERTY || secondAction == wxPG_ACTION_NEXT_PROPERTY )
             {
-                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();
-                }
-
+                selectDir = 1;
             }
-
-            if ( selectDir >= -1 )
+            else
             {
-                p = wxPropertyGridIterator::OneStep( m_pState, wxPG_ITERATE_VISIBLE, p, selectDir );
-                if ( p )
-                    DoSelectProperty(p);
+                event.Skip();
             }
+
+        }
+
+        if ( selectDir >= -1 )
+        {
+            p = wxPropertyGridIterator::OneStep( m_pState, wxPG_ITERATE_VISIBLE, p, selectDir );
+            if ( p )
+                DoSelectProperty(p);
         }
     }
     else
@@ -5146,74 +5089,15 @@ bool wxPropertyGrid::HandleChildKey( wxKeyEvent& event )
 
             // Update the control as well
             m_selected->GetEditorClass()->SetControlStringValue( m_selected,
-                                                                 m_wndEditor,
+                                                                 GetEditorControl(),
                                                                  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;
 }
@@ -5222,133 +5106,31 @@ bool wxPropertyGrid::HandleChildKey( wxKeyEvent& event )
 
 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 );
+    HandleKeyEvent( event );
 }
 
 // -----------------------------------------------------------------------
 
 void wxPropertyGrid::OnKeyUp(wxKeyEvent &event)
 {
-    m_keyComboConsumed = 0;
-
     event.Skip();
 }
 
 // -----------------------------------------------------------------------
 
-void wxPropertyGrid::OnNavigationKey( wxNavigationKeyEvent& event )
+bool wxPropertyGrid::ButtonTriggerKeyTest( int action, wxKeyEvent& event )
 {
-    // Ignore events that occur very close to focus set
-    if ( m_iFlags & wxPG_FL_IGNORE_NEXT_NAVKEY )
+    if ( action == -1 )
     {
-        m_iFlags &= ~(wxPG_FL_IGNORE_NEXT_NAVKEY);
-        event.Skip();
-        return;
+        int secondAction;
+        action = KeyEventToActions(event, &secondAction);
     }
 
-    wxPGProperty* next = (wxPGProperty*) NULL;
-
-    int dir = event.GetDirection()?1:-1;
-
-    if ( m_selected )
-    {
-        if ( dir == 1 && (m_wndEditor || m_wndEditor2) )
-        {
-            wxWindow* focused = wxWindow::FindFocus();
-
-            wxWindow* wndToCheck = GetEditorControl();
-
-            // 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;
-            }
-
-            /*
-            // Because of problems navigating from wxButton, do not go to it.
-            if ( !wndToCheck )
-            {
-                // No primary, use secondary
-                wndToCheck = m_wndEditor2;
-            }
-            // 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) )
-            {
-                wndToCheck = m_wndEditor2;
-                wxLogDebug(wxT("Exp1"));
-            }
-            */
-
-            if ( focused != wndToCheck &&
-                 wndToCheck )
-            {
-                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;
-            }
-        }
-
-        if ( !next )
-        {
-            next = wxPropertyGridIterator::OneStep(m_pState, wxPG_ITERATE_VISIBLE, m_selected, dir);
-
-            if ( next )
-            {
-                // This allows preventing NavigateOut to occur
-                DoSelectProperty( next, wxPG_SEL_FOCUS );
-            }
-        }
-    }
-
-    if ( !next )
-        event.Skip();
-}
-
-// -----------------------------------------------------------------------
-
-bool wxPropertyGrid::ButtonTriggerKeyTest( 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 ( action == wxPG_ACTION_PRESS_BUTTON &&
+         m_wndEditor2 )
     {
-        m_keyComboConsumed = 1;
-
-        wxCommandEvent evt(wxEVT_COMMAND_BUTTON_CLICKED,m_wndEditor2->GetId());
+        wxCommandEvent evt(wxEVT_COMMAND_BUTTON_CLICKED, m_wndEditor2->GetId());
         GetEventHandler()->AddPendingEvent(evt);
         return true;
     }
@@ -5370,7 +5152,7 @@ void wxPropertyGrid::OnChildKeyDown( wxKeyEvent &event )
         return;
     }
 
-    if ( ButtonTriggerKeyTest(event) )
+    if ( ButtonTriggerKeyTest(-1, event) )
         return;
 
     if ( HandleChildKey(event) == true )
@@ -5381,8 +5163,6 @@ void wxPropertyGrid::OnChildKeyDown( wxKeyEvent &event )
 
 void wxPropertyGrid::OnChildKeyUp( wxKeyEvent &event )
 {
-    m_keyComboConsumed = 0;
-
     GetEventHandler()->AddPendingEvent(event);
 
     event.Skip();
@@ -5429,13 +5209,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();
         }
@@ -5468,8 +5243,6 @@ void wxPropertyGrid::HandleFocusChange( wxWindow* newFocused )
 
             }
             */
-
-            m_iFlags &= ~(wxPG_FL_IGNORE_NEXT_NAVKEY);
         }
 
         // Redraw selected
@@ -5526,20 +5299,43 @@ void wxPropertyGrid::OnCaptureChange( wxMouseCaptureChangedEvent& WXUNUSED(event
 // -----------------------------------------------------------------------
 
 // noDefCheck = true prevents infinite recursion.
-wxPGEditor* wxPropertyGrid::RegisterEditorClass( wxPGEditor* editorclass,
-                                                 const wxString& name,
+wxPGEditor* wxPropertyGrid::RegisterEditorClass( wxPGEditor* editorClass,
                                                  bool noDefCheck )
 {
-    wxASSERT( editorclass );
+    wxASSERT( editorClass );
 
     if ( !noDefCheck && wxPGGlobalVars->m_mapEditorClasses.empty() )
         RegisterDefaultEditors();
 
-    wxPGGlobalVars->m_mapEditorClasses[name] = (void*)editorclass;
+    wxString name = editorClass->GetName();
 
-    return editorclass;
+    // 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" );
+
+    wxPGGlobalVars->m_mapEditorClasses[name] = (void*)editorClass;
+
+    return editorClass;
 }
 
+// Use this in RegisterDefaultEditors.
+#define wxPGRegisterDefaultEditorClass(EDITOR) \
+    if ( wxPGEditor_##EDITOR == (wxPGEditor*) NULL ) \
+    { \
+        wxPGEditor_##EDITOR = wxPropertyGrid::RegisterEditorClass( \
+            new wxPG##EDITOR##Editor, true ); \
+    }
+
 // Registers all default editor classes
 void wxPropertyGrid::RegisterDefaultEditors()
 {
@@ -5671,11 +5467,7 @@ void wxPGChoicesData::Clear()
         delete Item(i);
     }
 
-#if wxUSE_STL
-    m_items.resize(0);
-#else
-    m_items.Empty();
-#endif
+    m_items.clear();
 }
 
 void wxPGChoicesData::CopyDataFrom( wxPGChoicesData* data )
@@ -5820,7 +5612,8 @@ void wxPGChoices::RemoveAt(size_t nIndex, size_t count)
     unsigned int i;
     for ( i=nIndex; i<(nIndex+count); i++)
         delete m_data->Item(i);
-    m_data->m_items.RemoveAt(nIndex, count);
+    m_data->m_items.erase(m_data->m_items.begin()+nIndex,
+                          m_data->m_items.begin()+nIndex+count);
 }
 
 // -----------------------------------------------------------------------