]> git.saurik.com Git - wxWidgets.git/blobdiff - src/propgrid/editors.cpp
missing commit
[wxWidgets.git] / src / propgrid / editors.cpp
index 6088249d8658f1e0851dc8ce7ab1953ed5808993..1817abc615da44aaeb0387bc003d073ec9e2f0ec 100644 (file)
@@ -4,9 +4,9 @@
 // Author:      Jaakko Salli
 // Modified by:
 // Created:     2007-04-14
-// RCS-ID:      $Id:
+// RCS-ID:      $Id$
 // Copyright:   (c) Jaakko Salli
-// Licence:     wxWindows license
+// Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
 // For compilers that support precompilation, includes "wx/wx.h".
@@ -16,6 +16,8 @@
     #pragma hdrstop
 #endif
 
+#if wxUSE_PROPGRID
+
 #ifndef WX_PRECOMP
     #include "wx/defs.h"
     #include "wx/object.h"
@@ -39,7 +41,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/props.h>
+#include "wx/propgrid/propgrid.h"
+#include "wx/propgrid/editors.h"
+#include "wx/propgrid/props.h"
 
 #if wxPG_USE_RENDERER_NATIVE
-    #include <wx/renderer.h>
+    #include "wx/renderer.h"
 #endif
 
 // How many pixels between textctrl and button
 #ifdef __WXMAC__
-    #define wxPG_TEXTCTRL_AND_BUTTON_SPACING        8
+    #define wxPG_TEXTCTRL_AND_BUTTON_SPACING        4
 #else
     #define wxPG_TEXTCTRL_AND_BUTTON_SPACING        2
-#endif 
+#endif
 
 #define wxPG_BUTTON_SIZEDEC                         0
 
-#include <wx/odcombo.h>
-
-#ifdef __WXMSW__
-    #include <wx/msw/private.h>
-#endif
+#include "wx/odcombo.h"
 
 // -----------------------------------------------------------------------
 
 #if defined(__WXMSW__)
     // tested
-    #define wxPG_NAT_TEXTCTRL_BORDER_X          0 // Unremovable border of native textctrl.
-    #define wxPG_NAT_TEXTCTRL_BORDER_Y          0 // Unremovable border of native textctrl.
-
     #define wxPG_NAT_BUTTON_BORDER_ANY          1
     #define wxPG_NAT_BUTTON_BORDER_X            1
     #define wxPG_NAT_BUTTON_BORDER_Y            1
 
 #elif defined(__WXGTK__)
     // tested
-    #define wxPG_CHECKMARK_XADJ                 0
-    #define wxPG_CHECKMARK_YADJ                 0
-    #define wxPG_CHECKMARK_WADJ                 (-1)
-    #define wxPG_CHECKMARK_HADJ                 (-1)
+    #define wxPG_CHECKMARK_XADJ                 1
+    #define wxPG_CHECKMARK_YADJ                 1
+    #define wxPG_CHECKMARK_WADJ                 (-2)
+    #define wxPG_CHECKMARK_HADJ                 (-2)
     #define wxPG_CHECKMARK_DEFLATE              3
 
-    #define wxPG_NAT_TEXTCTRL_BORDER_X      3 // Unremovable border of native textctrl.
-    #define wxPG_NAT_TEXTCTRL_BORDER_Y      3 // Unremovable border of native textctrl.
-
     #define wxPG_NAT_BUTTON_BORDER_ANY      1
     #define wxPG_NAT_BUTTON_BORDER_X        1
     #define wxPG_NAT_BUTTON_BORDER_Y        1
 
 #elif defined(__WXMAC__)
     // *not* tested
-    #define wxPG_CHECKMARK_XADJ                 0
-    #define wxPG_CHECKMARK_YADJ                 0
-    #define wxPG_CHECKMARK_WADJ                 0
-    #define wxPG_CHECKMARK_HADJ                 0
+    #define wxPG_CHECKMARK_XADJ                 4
+    #define wxPG_CHECKMARK_YADJ                 4
+    #define wxPG_CHECKMARK_WADJ                 -6
+    #define wxPG_CHECKMARK_HADJ                 -6
     #define wxPG_CHECKMARK_DEFLATE              0
 
-    #define wxPG_NAT_TEXTCTRL_BORDER_X      0 // Unremovable border of native textctrl.
-    #define wxPG_NAT_TEXTCTRL_BORDER_Y      0 // Unremovable border of native textctrl.
-
     #define wxPG_NAT_BUTTON_BORDER_ANY      0
     #define wxPG_NAT_BUTTON_BORDER_X        0
     #define wxPG_NAT_BUTTON_BORDER_Y        0
 
-    #define wxPG_TEXTCTRLYADJUST            3
+    #define wxPG_TEXTCTRLYADJUST            0
 
 #else
     // defaults
     #define wxPG_CHECKMARK_HADJ                 0
     #define wxPG_CHECKMARK_DEFLATE              0
 
-    #define wxPG_NAT_TEXTCTRL_BORDER_X      0 // Unremovable border of native textctrl.
-    #define wxPG_NAT_TEXTCTRL_BORDER_Y      0 // Unremovable border of native textctrl.
-
     #define wxPG_NAT_BUTTON_BORDER_ANY      0
     #define wxPG_NAT_BUTTON_BORDER_X        0
     #define wxPG_NAT_BUTTON_BORDER_Y        0
 
 #endif
 
-#if (!wxPG_NAT_TEXTCTRL_BORDER_X && !wxPG_NAT_TEXTCTRL_BORDER_Y)
-    #define wxPG_ENABLE_CLIPPER_WINDOW      0
-#else
-    #define wxPG_ENABLE_CLIPPER_WINDOW      1
-#endif
-
-
 // for odcombo
+#ifdef __WXMAC__
+#define wxPG_CHOICEXADJUST           -3 // required because wxComboCtrl reserves 3pixels for wxTextCtrl's focus ring
+#define wxPG_CHOICEYADJUST           -3
+#else
 #define wxPG_CHOICEXADJUST           0
 #define wxPG_CHOICEYADJUST           0
+#endif
 
-#define ODCB_CUST_PAINT_MARGIN               6  // Number added to image width for SetCustomPaintWidth
+// Number added to image width for SetCustomPaintWidth
+#define ODCB_CUST_PAINT_MARGIN               6
 
-// Milliseconds to wait for two mouse-ups after focus inorder
+// Milliseconds to wait for two mouse-ups after focus in order
 // to trigger a double-click.
 #define DOUBLE_CLICK_CONVERSION_TRESHOLD        500
 
@@ -180,10 +164,16 @@ wxPGEditor::~wxPGEditor()
 {
 }
 
-void wxPGEditor::DrawValue( wxDC& dc, const wxRect& rect, wxPGProperty* property, const wxString& text ) const
+wxString wxPGEditor::GetName() const
 {
-    if ( !property->IsValueUnspecified() )
-        dc.DrawText( text, rect.x+wxPG_XBEFORETEXT, rect.y );
+    return GetClassInfo()->GetClassName();
+}
+
+void wxPGEditor::DrawValue( wxDC& dc, const wxRect& rect,
+                            wxPGProperty* WXUNUSED(property),
+                            const wxString& text ) const
+{
+    dc.DrawText( text, rect.x+wxPG_XBEFORETEXT, rect.y );
 }
 
 bool wxPGEditor::GetValueFromControl( wxVariant&, wxPGProperty*, wxWindow* ) const
@@ -217,206 +207,119 @@ void wxPGEditor::OnFocus( wxPGProperty*, wxWindow* ) const
 {
 }
 
-
-bool wxPGEditor::CanContainCustomImage() const
-{
-    return false;
-}
-
-// -----------------------------------------------------------------------
-// wxPGClipperWindow
-// -----------------------------------------------------------------------
-
-
-#if wxPG_ENABLE_CLIPPER_WINDOW
-
-//
-// Clipper window is used to "remove" borders from controls
-// which otherwise insist on having them despite of supplied
-// wxNO_BORDER window style.
-//
-class wxPGClipperWindow : public wxWindow
+void wxPGEditor::SetControlAppearance( wxPropertyGrid* pg,
+                                       wxPGProperty* property,
+                                       wxWindow* ctrl,
+                                       const wxPGCell& cell,
+                                       const wxPGCell& oCell,
+                                       bool unspecified ) const
 {
-    DECLARE_CLASS(wxPGClipperWindow)
-public:
-
-    wxPGClipperWindow()
-        : wxWindow()
+    // Get old editor appearance
+    wxTextCtrl* tc = NULL;
+    wxComboCtrl* cb = NULL;
+    if ( wxDynamicCast(ctrl, wxTextCtrl) )
     {
-        wxPGClipperWindow::Init();
+        tc = (wxTextCtrl*) ctrl;
     }
-
-    wxPGClipperWindow(wxWindow* parent,
-                      wxWindowID id,
-                      const wxPoint& pos = wxDefaultPosition,
-                      const wxSize& size = wxDefaultSize)
+    else
     {
-        Init();
-        Create(parent,id,pos,size);
+        if ( wxDynamicCast(ctrl, wxComboCtrl) )
+        {
+            cb = (wxComboCtrl*) ctrl;
+            tc = cb->GetTextCtrl();
+        }
     }
 
-    void Create(wxWindow* parent,
-                wxWindowID id,
-                const wxPoint& pos = wxDefaultPosition,
-                const wxSize& size = wxDefaultSize);
-
-    virtual ~wxPGClipperWindow();
-
-    virtual bool ProcessEvent(wxEvent& event);
-
-    inline wxWindow* GetControl() const { return m_ctrl; }
-
-    // This is called before wxControl is constructed.
-    void GetControlRect( int xadj, int yadj, wxPoint& pt, wxSize& sz );
-
-    // This is caleed after wxControl has been constructed.
-    void SetControl( wxWindow* ctrl );
-
-    virtual void Refresh( bool eraseBackground = true,
-                          const wxRect *rect = (const wxRect *) NULL );
-    virtual void SetFocus();
-
-    virtual bool SetFont(const wxFont& font);
-
-    inline int GetXClip() const { return m_xadj; }
-
-    inline int GetYClip() const { return m_yadj; }
+    if ( tc || cb )
+    {
+        wxString tcText;
+        bool changeText = false;
 
-protected:
-    wxWindow*       m_ctrl;
+        if ( cell.HasText() && !pg->IsEditorFocused() )
+        {
+            tcText = cell.GetText();
+            changeText = true;
+        }
+        else if ( oCell.HasText() )
+        {
+            tcText = property->GetValueAsString(
+                property->HasFlag(wxPG_PROP_READONLY)?0:wxPG_EDITABLE_VALUE);
+            changeText = true;
+        }
 
-    int             m_xadj; // Horizontal border clip.
+        if ( changeText )
+        {
+            // This prevents value from being modified
+            if ( tc )
+            {
+                pg->SetupTextCtrlValue(tcText);
+                tc->SetValue(tcText);
+            }
+            else
+            {
+                cb->SetText(tcText);
+            }
+        }
+    }
 
-    int             m_yadj; // Vertical border clip.
+    // Do not make the mistake of calling GetClassDefaultAttributes()
+    // here. It is static, while GetDefaultAttributes() is virtual
+    // and the correct one to use.
+    wxVisualAttributes vattrs = ctrl->GetDefaultAttributes();
 
-private:
-    void Init ()
+    // Foreground colour
+    const wxColour& fgCol = cell.GetFgCol();
+    if ( fgCol.IsOk() )
     {
-        m_ctrl = (wxWindow*) NULL;
+        ctrl->SetForegroundColour(fgCol);
+    }
+    else if ( oCell.GetFgCol().IsOk() )
+    {
+        ctrl->SetForegroundColour(vattrs.colFg);
     }
-};
-
-
-IMPLEMENT_CLASS(wxPGClipperWindow,wxWindow)
-
-
-// This is called before wxControl is constructed.
-void wxPGClipperWindow::GetControlRect( int xadj, int yadj, wxPoint& pt, wxSize& sz )
-{
-    m_xadj = xadj;
-    m_yadj = yadj;
-    pt.x = -xadj;
-    pt.y = -yadj;
-    wxSize own_size = GetSize();
-    sz.x = own_size.x+(xadj*2);
-    sz.y = own_size.y+(yadj*2);
-}
-
-
-// This is caleed after wxControl has been constructed.
-void wxPGClipperWindow::SetControl( wxWindow* ctrl )
-{
-    m_ctrl = ctrl;
-
-    // GTK requires this.
-    ctrl->SetSizeHints(3,3);
-
-    // Correct size of this window to match the child.
-    wxSize sz = GetSize();
-    wxSize chsz = ctrl->GetSize();
-
-    int hei_adj = chsz.y - (sz.y+(m_yadj*2));
-    if ( hei_adj )
-        SetSize(sz.x,chsz.y-(m_yadj*2));
-
-}
-
-
-void wxPGClipperWindow::Refresh( bool eraseBackground, const wxRect *rect )
-{
-    wxWindow::Refresh(false,rect);
-    if ( m_ctrl )
-        m_ctrl->Refresh(eraseBackground);
-}
-
-
-// Pass focus to control
-void wxPGClipperWindow::SetFocus()
-{
-    if ( m_ctrl )
-        m_ctrl->SetFocus();
-    else
-        wxWindow::SetFocus();
-}
-
 
-bool wxPGClipperWindow::SetFont(const wxFont& font)
-{
-    bool res = wxWindow::SetFont(font);
-    if ( m_ctrl )
-        return m_ctrl->SetFont(font);
-    return res;
-}
+    // Background colour
+    const wxColour& bgCol = cell.GetBgCol();
+    if ( bgCol.IsOk() )
+    {
+        ctrl->SetBackgroundColour(bgCol);
+    }
+    else if ( oCell.GetBgCol().IsOk() )
+    {
+        ctrl->SetBackgroundColour(vattrs.colBg);
+    }
 
+    // Font
+    const wxFont& font = cell.GetFont();
+    if ( font.IsOk() )
+    {
+        ctrl->SetFont(font);
+    }
+    else if ( oCell.GetFont().IsOk() )
+    {
+        ctrl->SetFont(vattrs.font);
+    }
 
-void wxPGClipperWindow::Create(wxWindow* parent,
-                               wxWindowID id,
-                               const wxPoint& pos,
-                               const wxSize& size )
-{
-    wxWindow::Create(parent,id,pos,size);
+    // Also call the old SetValueToUnspecified()
+    if ( unspecified )
+        SetValueToUnspecified(property, ctrl);
 }
 
-
-wxPGClipperWindow::~wxPGClipperWindow()
+void wxPGEditor::SetValueToUnspecified( wxPGProperty* WXUNUSED(property),
+                                        wxWindow* WXUNUSED(ctrl) ) const
 {
 }
 
-
-bool wxPGClipperWindow::ProcessEvent(wxEvent& event)
+bool wxPGEditor::CanContainCustomImage() const
 {
-    if ( event.GetEventType() == wxEVT_SIZE )
-    {
-        if ( m_ctrl )
-        {
-            // Maintain correct size relationship.
-            wxSize sz = GetSize();
-            m_ctrl->SetSize(sz.x+(m_xadj*2),sz.y+(m_yadj*2));
-            event.Skip();
-            return false;
-        }
-    }
-    return wxWindow::ProcessEvent(event);
+    return false;
 }
 
-#endif // wxPG_ENABLE_CLIPPER_WINDOW
-
-/*wxWindow* wxPropertyGrid::GetActualEditorControl( wxWindow* ctrl )
-{
-#if wxPG_ENABLE_CLIPPER_WINDOW
-    // Pass real control instead of clipper window
-    if ( ctrl->IsKindOf(CLASSINFO(wxPGClipperWindow)) )
-    {
-        return ((wxPGClipperWindow*)ctrl)->GetControl();
-    }
-#else
-    return ctrl;
-#endif
-}*/
-
 // -----------------------------------------------------------------------
 // wxPGTextCtrlEditor
 // -----------------------------------------------------------------------
 
-// Clipper window support macro (depending on whether it is used
-// for this editor or not)
-#if wxPG_NAT_TEXTCTRL_BORDER_X || wxPG_NAT_TEXTCTRL_BORDER_Y
-    #define wxPG_NAT_TEXTCTRL_BORDER_ANY    1
-#else
-    #define wxPG_NAT_TEXTCTRL_BORDER_ANY    0
-#endif
-
-WX_PG_IMPLEMENT_EDITOR_CLASS(TextCtrl,wxPGTextCtrlEditor,wxPGEditor)
+WX_PG_IMPLEMENT_INTERNAL_EDITOR_CLASS(TextCtrl,wxPGTextCtrlEditor,wxPGEditor)
 
 
 wxPGWindowList wxPGTextCtrlEditor::CreateControls( wxPropertyGrid* propGrid,
@@ -430,17 +333,20 @@ wxPGWindowList wxPGTextCtrlEditor::CreateControls( wxPropertyGrid* propGrid,
     // If has children, and limited editing is specified, then don't create.
     if ( (property->GetFlags() & wxPG_PROP_NOEDITOR) &&
          property->GetChildCount() )
-        return (wxWindow*) NULL;
+        return NULL;
 
-    if ( !property->IsValueUnspecified() )
-        text = property->GetValueString(property->HasFlag(wxPG_PROP_READONLY)?0:wxPG_EDITABLE_VALUE);
+    int argFlags = 0;
+    if ( !property->HasFlag(wxPG_PROP_READONLY) &&
+         !property->IsValueUnspecified() )
+        argFlags |= wxPG_EDITABLE_VALUE;
+    text = property->GetValueAsString(argFlags);
 
     int flags = 0;
     if ( (property->GetFlags() & wxPG_PROP_PASSWORD) &&
-         property->IsKindOf(CLASSINFO(wxStringProperty)) )
+         wxDynamicCast(property, wxStringProperty) )
         flags |= wxTE_PASSWORD;
 
-    wxWindow* wnd = propGrid->GenerateEditorTextCtrl(pos,sz,text,(wxWindow*)NULL,flags,
+    wxWindow* wnd = propGrid->GenerateEditorTextCtrl(pos,sz,text,NULL,flags,
                                                      property->GetMaxLength());
 
     return wnd;
@@ -479,9 +385,16 @@ void wxPGTextCtrlEditor::UpdateControl( wxPGProperty* property, wxWindow* ctrl )
     else
         s = property->GetDisplayedString();
 
-    tc->SetValue(s);    
-}
+    wxPropertyGrid* pg = property->GetGrid();
 
+    pg->SetupTextCtrlValue(s);
+    tc->SetValue(s);
+
+    //
+    // Fix indentation, just in case (change in font boldness is one good
+    // reason).
+    tc->SetMargins(0);
+}
 
 // Provided so that, for example, ComboBox editor can use the same code
 // (multiple inheritance would get way too messy).
@@ -493,14 +406,14 @@ bool wxPGTextCtrlEditor::OnTextCtrlEvent( wxPropertyGrid* propGrid,
     if ( !ctrl )
         return false;
 
-    if ( event.GetEventType() == wxEVT_COMMAND_TEXT_ENTER )
+    if ( event.GetEventType() == wxEVT_TEXT_ENTER )
     {
         if ( propGrid->IsEditorsValueModified() )
         {
             return true;
         }
     }
-    else if ( event.GetEventType() == wxEVT_COMMAND_TEXT_UPDATED )
+    else if ( event.GetEventType() == wxEVT_TEXT )
     {
         //
         // Pass this event outside wxPropertyGrid so that,
@@ -531,7 +444,7 @@ bool wxPGTextCtrlEditor::GetTextCtrlValueFromControl( wxVariant& variant, wxPGPr
     wxTextCtrl* tc = wxStaticCast(ctrl, wxTextCtrl);
     wxString textVal = tc->GetValue();
 
-    if ( property->UsesAutoUnspecified() && !textVal.length() )
+    if ( property->UsesAutoUnspecified() && textVal.empty() )
     {
         variant.MakeNull();
         return true;
@@ -555,37 +468,51 @@ bool wxPGTextCtrlEditor::GetValueFromControl( wxVariant& variant, wxPGProperty*
 }
 
 
-void wxPGTextCtrlEditor::SetValueToUnspecified( wxPGProperty* property, wxWindow* ctrl ) const
+void wxPGTextCtrlEditor::SetControlStringValue( wxPGProperty* property, wxWindow* ctrl, const wxString& txt ) const
 {
     wxTextCtrl* tc = wxStaticCast(ctrl, wxTextCtrl);
 
     wxPropertyGrid* pg = property->GetGrid();
     wxASSERT(pg);  // Really, property grid should exist if editor does
     if ( pg )
-        tc->SetValue(wxEmptyString);
+    {
+        pg->SetupTextCtrlValue(txt);
+        tc->SetValue(txt);
+    }
 }
 
 
-void wxPGTextCtrlEditor::SetControlStringValue( wxPGProperty* property, wxWindow* ctrl, const wxString& txt ) const
+void wxPGTextCtrlEditor_OnFocus( wxPGProperty* property,
+                                 wxTextCtrl* tc )
 {
-    wxTextCtrl* tc = wxStaticCast(ctrl, wxTextCtrl);
+    // Make sure there is correct text (instead of unspecified value
+    // indicator or hint text)
+    int flags = property->HasFlag(wxPG_PROP_READONLY) ?
+        0 : wxPG_EDITABLE_VALUE;
+    wxString correctText = property->GetValueAsString(flags);
 
-    wxPropertyGrid* pg = property->GetGrid();
-    wxASSERT(pg);  // Really, property grid should exist if editor does
-    if ( pg )
-        tc->SetValue(txt);
-}
+    if ( tc->GetValue() != correctText )
+    {
+        property->GetGrid()->SetupTextCtrlValue(correctText);
+        tc->SetValue(correctText);
+    }
 
+    tc->SelectAll();
+}
 
-void wxPGTextCtrlEditor::OnFocus( wxPGProperty*, wxWindow* wnd ) const
+void wxPGTextCtrlEditor::OnFocus( wxPGProperty* property,
+                                  wxWindow* wnd ) const
 {
     wxTextCtrl* tc = wxStaticCast(wnd, wxTextCtrl);
-
-    tc->SetSelection(-1,-1);
+    wxPGTextCtrlEditor_OnFocus(property, tc);
 }
 
-
-wxPGTextCtrlEditor::~wxPGTextCtrlEditor() { }
+wxPGTextCtrlEditor::~wxPGTextCtrlEditor()
+{
+    // Reset the global pointer. Useful when wxPropertyGrid is accessed
+    // from an external main loop.
+    wxPG_EDITOR(TextCtrl) = NULL;
+}
 
 
 // -----------------------------------------------------------------------
@@ -593,7 +520,7 @@ wxPGTextCtrlEditor::~wxPGTextCtrlEditor() { }
 // -----------------------------------------------------------------------
 
 
-WX_PG_IMPLEMENT_EDITOR_CLASS(Choice,wxPGChoiceEditor,wxPGEditor)
+WX_PG_IMPLEMENT_INTERNAL_EDITOR_CLASS(Choice,wxPGChoiceEditor,wxPGEditor)
 
 
 // This is a special enhanced double-click processor class.
@@ -620,7 +547,7 @@ protected:
         int evtType = event.GetEventType();
 
         if ( m_property->HasFlag(wxPG_PROP_USE_DCC) &&
-             m_property->IsKindOf(CLASSINFO(wxBoolProperty)) &&
+             wxDynamicCast(m_property, wxBoolProperty) &&
              !m_combo->IsPopupShown() )
         {
             // Just check that it is in the text area
@@ -690,7 +617,7 @@ public:
     wxPGComboBox()
         : wxOwnerDrawnComboBox()
     {
-        m_dclickProcessor = (wxPGDoubleClickProcessor*) NULL;
+        m_dclickProcessor = NULL;
         m_sizeEventCalled = false;
     }
 
@@ -724,31 +651,47 @@ public:
                                             name ) )
             return false;
 
-        m_dclickProcessor = new wxPGDoubleClickProcessor(this, GetGrid()->GetSelection() );
+        m_dclickProcessor = new
+            wxPGDoubleClickProcessor( this, GetGrid()->GetSelection() );
 
         PushEventHandler(m_dclickProcessor);
 
         return true;
     }
 
-    virtual void OnDrawItem( wxDC& dc, const wxRect& rect, int item, int flags ) const
+    virtual void OnDrawItem( wxDC& dc,
+                             const wxRect& rect,
+                             int item,
+                             int flags ) const
     {
         wxPropertyGrid* pg = GetGrid();
-        pg->OnComboItemPaint((wxPGCustomComboControl*)this,item,dc,(wxRect&)rect,flags);
+
+        // Handle hint text via super class
+        if ( (flags & wxODCB_PAINTING_CONTROL) &&
+             ShouldUseHintText(flags) )
+        {
+            wxOwnerDrawnComboBox::OnDrawItem(dc, rect, item, flags);
+        }
+        else
+        {
+            pg->OnComboItemPaint( this, item, &dc, (wxRect&)rect, flags );
+        }
     }
+
     virtual wxCoord OnMeasureItem( size_t item ) const
     {
         wxPropertyGrid* pg = GetGrid();
         wxRect rect;
         rect.x = -1;
         rect.width = 0;
-        pg->OnComboItemPaint((wxPGCustomComboControl*)this,item,*((wxDC*)NULL),rect,0);
+        pg->OnComboItemPaint( this, item, NULL, rect, 0 );
         return rect.height;
     }
 
     wxPropertyGrid* GetGrid() const
     {
-        wxPropertyGrid* pg = wxDynamicCast(GetParent()->GetParent(),wxPropertyGrid);
+        wxPropertyGrid* pg = wxDynamicCast(GetParent(),
+                                           wxPropertyGrid);
         wxASSERT(pg);
         return pg;
     }
@@ -759,15 +702,20 @@ public:
         wxRect rect;
         rect.x = -1;
         rect.width = -1;
-        pg->OnComboItemPaint((wxPGCustomComboControl*)this,item,*((wxDC*)NULL),rect,0);
+        pg->OnComboItemPaint( this, item, NULL, rect, 0 );
         return rect.width;
     }
 
-    virtual void PositionTextCtrl( int WXUNUSED(textCtrlXAdjust), int WXUNUSED(textCtrlYAdjust) )
+    virtual void PositionTextCtrl( int textCtrlXAdjust,
+                                   int WXUNUSED(textCtrlYAdjust) )
     {
         wxPropertyGrid* pg = GetGrid();
+    #ifdef wxPG_TEXTCTRLXADJUST
+        textCtrlXAdjust = wxPG_TEXTCTRLXADJUST -
+                          (wxPG_XBEFOREWIDGET+wxPG_CONTROL_MARGIN+1) - 1,
+    #endif
         wxOwnerDrawnComboBox::PositionTextCtrl(
-            wxPG_TEXTCTRLXADJUST - (wxPG_XBEFOREWIDGET+wxPG_CONTROL_MARGIN+1) - 1,
+            textCtrlXAdjust,
             pg->GetSpacingY() + 2
         );
     }
@@ -778,25 +726,24 @@ private:
 };
 
 
-void wxPropertyGrid::OnComboItemPaint( wxPGCustomComboControl* pCc,
+void wxPropertyGrid::OnComboItemPaint( const wxPGComboBox* pCb,
                                        int item,
-                                       wxDC& dc,
+                                       wxDC* pDc,
                                        wxRect& rect,
                                        int flags )
 {
-    wxPGComboBox* pCb = (wxPGComboBox*)pCc;
-
-    // Sanity check
-    wxASSERT( IsKindOf(CLASSINFO(wxPropertyGrid)) );
-
-    wxPGProperty* p = m_selected;
+    wxPGProperty* p = GetSelection();
     wxString text;
 
-    const wxPGChoices* pChoices = &p->GetChoices();
+    const wxPGChoices& choices = p->GetChoices();
     const wxPGCommonValue* comVal = NULL;
-    int choiceCount = p->GetChoiceCount();
     int comVals = p->GetDisplayedCommonValueCount();
     int comValIndex = -1;
+
+    int choiceCount = 0;
+    if ( choices.IsOk() )
+        choiceCount = choices.GetCount();
+
     if ( item >= choiceCount && comVals > 0 )
     {
         comValIndex = item - choiceCount;
@@ -813,7 +760,7 @@ void wxPropertyGrid::OnComboItemPaint( wxPGCustomComboControl* pCc,
         else
         {
             if ( !p->IsValueUnspecified() )
-                text = p->GetValueString(0);
+                text = p->GetValueAsString(0);
         }
     }
 
@@ -824,8 +771,8 @@ void wxPropertyGrid::OnComboItemPaint( wxPGCustomComboControl* pCc,
 
     const wxBitmap* itemBitmap = NULL;
 
-    if ( item >= 0 && pChoices && pChoices->Item(item).GetBitmap().Ok() && comValIndex == -1 )
-        itemBitmap = &pChoices->Item(item).GetBitmap();
+    if ( item >= 0 && choices.IsOk() && choices.Item(item).GetBitmap().IsOk() && comValIndex == -1 )
+        itemBitmap = &choices.Item(item).GetBitmap();
 
     //
     // Decide what custom image size to use
@@ -845,7 +792,7 @@ void wxPropertyGrid::OnComboItemPaint( wxPGCustomComboControl* pCc,
         if ( rect.width < 0 )
         {
             wxCoord x, y;
-            GetTextExtent(text, &x, &y, 0, 0, &m_font);
+            pCb->GetTextExtent(text, &x, &y, 0, 0);
             rect.width = cis.x + wxCC_CUSTOM_IMAGE_MARGIN1 + wxCC_CUSTOM_IMAGE_MARGIN2 + 9 + x;
         }
 
@@ -861,30 +808,64 @@ void wxPropertyGrid::OnComboItemPaint( wxPGCustomComboControl* pCc,
     if ( (flags & wxODCB_PAINTING_CONTROL) )
         paintdata.m_choiceItem = -1;
 
-    if ( &dc )
-        dc.SetBrush(*wxWHITE_BRUSH);
+    if ( pDc )
+        pDc->SetBrush(*wxWHITE_BRUSH);
+
+    wxPGCellRenderer* renderer = NULL;
+    const wxPGChoiceEntry* cell = NULL;
 
     if ( rect.x >= 0 )
     {
         //
         // DrawItem call
+        wxDC& dc = *pDc;
 
         wxPoint pt(rect.x + wxPG_CONTROL_MARGIN - wxPG_CHOICEXADJUST - 1,
                    rect.y + 1);
 
-        int renderFlags = 0;
+        int renderFlags = wxPGCellRenderer::DontUseCellColours;
+        bool useCustomPaintProcedure;
 
-        if ( flags & wxODCB_PAINTING_CONTROL )
-            renderFlags |= wxPGCellRenderer::Control;
+        // If custom image had some size, we will start from the assumption
+        // that custom paint procedure is required
+        if ( cis.x > 0 )
+            useCustomPaintProcedure = true;
+        else
+            useCustomPaintProcedure = false;
 
         if ( flags & wxODCB_PAINTING_SELECTED )
             renderFlags |= wxPGCellRenderer::Selected;
 
-        if ( cis.x > 0 && (p->HasFlag(wxPG_PROP_CUSTOMIMAGE) || !(flags & wxODCB_PAINTING_CONTROL)) &&
-             ( !p->m_valueBitmap || item == pCb->GetSelection() ) &&
-             ( item >= 0 || (flags & wxODCB_PAINTING_CONTROL) ) &&
-             !itemBitmap
-           )
+        if ( flags & wxODCB_PAINTING_CONTROL )
+        {
+            renderFlags |= wxPGCellRenderer::Control;
+
+            // If wxPG_PROP_CUSTOMIMAGE was set, then that means any custom
+            // image will not appear on the control row (it may be too
+            // large to fit, for instance). Also do not draw custom image
+            // if no choice was selected.
+            if ( !p->HasFlag(wxPG_PROP_CUSTOMIMAGE) || item < 0 )
+                useCustomPaintProcedure = false;
+        }
+        else
+        {
+            renderFlags |= wxPGCellRenderer::ChoicePopup;
+
+            // For consistency, always use normal font when drawing drop down
+            // items
+            dc.SetFont(GetFont());
+        }
+
+        // If not drawing a selected popup item, then give property's
+        // m_valueBitmap a chance.
+        if ( p->m_valueBitmap && item != pCb->GetSelection() )
+            useCustomPaintProcedure = false;
+        // If current choice had a bitmap set by the application, then
+        // use it instead of any custom paint procedure.
+        else if ( itemBitmap )
+            useCustomPaintProcedure = false;
+
+        if ( useCustomPaintProcedure )
         {
             pt.x += wxCC_CUSTOM_IMAGE_MARGIN1;
             wxRect r(pt.x,pt.y,cis.x,cis.y);
@@ -901,7 +882,7 @@ void wxPropertyGrid::OnComboItemPaint( wxPGCustomComboControl* pCc,
             if ( comValIndex >= 0 )
             {
                 const wxPGCommonValue* cv = GetCommonValue(comValIndex);
-                wxPGCellRenderer* renderer = cv->GetRenderer();
+                renderer = cv->GetRenderer();
                 r.width = rect.width;
                 renderer->Render( dc, r, this, p, m_selColumn, comValIndex, renderFlags );
                 return;
@@ -927,13 +908,15 @@ void wxPropertyGrid::OnComboItemPaint( wxPGCustomComboControl* pCc,
             if ( item < 0 && (flags & wxODCB_PAINTING_CONTROL) )
                 item = pCb->GetSelection();
 
-            if ( pChoices && item >= 0 && comValIndex < 0 )
+            if ( choices.IsOk() && item >= 0 && comValIndex < 0 )
             {
-                const wxPGChoiceEntry& cell = pChoices->Item(item);
-                wxPGCellRenderer* renderer = wxPGGlobalVars->m_defaultRenderer;
-                int imageOffset = renderer->PreDrawCell( dc, rect, cell, renderFlags );
+                cell = &choices.Item(item);
+                renderer = wxPGGlobalVars->m_defaultRenderer;
+                int imageOffset = renderer->PreDrawCell(dc, rect, *cell,
+                                                        renderFlags );
                 if ( imageOffset )
-                    imageOffset += wxCC_CUSTOM_IMAGE_MARGIN1 + wxCC_CUSTOM_IMAGE_MARGIN2;
+                    imageOffset += wxCC_CUSTOM_IMAGE_MARGIN1 +
+                                   wxCC_CUSTOM_IMAGE_MARGIN2;
                 pt.x += imageOffset;
             }
         }
@@ -947,11 +930,15 @@ void wxPropertyGrid::OnComboItemPaint( wxPGCustomComboControl* pCc,
         pt.x += 1;
 
         dc.DrawText( text, pt.x + wxPG_XBEFORETEXT, pt.y );
+
+        if ( renderer )
+            renderer->PostDrawCell(dc, this, *cell, renderFlags);
     }
     else
     {
         //
         // MeasureItem call
+        wxDC& dc = *pDc;
 
         p->OnCustomPaint( dc, rect, paintdata );
         rect.height = paintdata.m_drawnHeight + 2;
@@ -964,23 +951,35 @@ bool wxPGChoiceEditor_SetCustomPaintWidth( wxPropertyGrid* propGrid, wxPGComboBo
     wxPGProperty* property = propGrid->GetSelectedProperty();
     wxASSERT( property );
 
+    wxSize imageSize;
+    bool res;
+
+    // TODO: Do this always when cell has custom text.
+    if ( property->IsValueUnspecified() )
+    {
+        cb->SetCustomPaintWidth( 0 );
+        return true;
+    }
+
     if ( cmnVal >= 0 )
     {
         // Yes, a common value is being selected
         property->SetCommonValue( cmnVal );
-        wxSize imageSize = propGrid->GetCommonValue(cmnVal)->
+        imageSize = propGrid->GetCommonValue(cmnVal)->
                             GetRenderer()->GetImageSize(property, 1, cmnVal);
-        if ( imageSize.x ) imageSize.x += ODCB_CUST_PAINT_MARGIN;
-        cb->SetCustomPaintWidth( imageSize.x );
-        return false;
+        res = false;
     }
     else
     {
-        wxSize imageSize = propGrid->GetImageSize(property, -1);
-        if ( imageSize.x ) imageSize.x += ODCB_CUST_PAINT_MARGIN;
-        cb->SetCustomPaintWidth( imageSize.x );
-        return true;
+        imageSize = propGrid->GetImageSize(property, -1);
+        res = true;
     }
+
+    if ( imageSize.x )
+        imageSize.x += ODCB_CUST_PAINT_MARGIN;
+    cb->SetCustomPaintWidth( imageSize.x );
+
+    return res;
 }
 
 // CreateControls calls this with CB_READONLY in extraStyle
@@ -990,19 +989,21 @@ wxWindow* wxPGChoiceEditor::CreateControlsBase( wxPropertyGrid* propGrid,
                                                 const wxSize& sz,
                                                 long extraStyle ) const
 {
-    wxString        defString;
-
-    // Get choices.
-    int index = property->GetChoiceInfo( NULL );
-
-    bool isUnspecified = property->IsValueUnspecified();
-
-    if ( isUnspecified )
-        index = -1;
-    else
-        defString = property->GetDisplayedString();
+    // Since it is not possible (yet) to create a read-only combo box in
+    // the same sense that wxTextCtrl is read-only, simply do not create
+    // the control in this case.
+    if ( property->HasFlag(wxPG_PROP_READONLY) )
+        return NULL;
 
     const wxPGChoices& choices = property->GetChoices();
+    wxString defString;
+    int index = property->GetChoiceSelection();
+
+    int argFlags = 0;
+    if ( !property->HasFlag(wxPG_PROP_READONLY) &&
+         !property->IsValueUnspecified() )
+        argFlags |= wxPG_EDITABLE_VALUE;
+    defString = property->GetValueAsString(argFlags);
 
     wxArrayString labels = choices.GetLabels();
 
@@ -1017,14 +1018,18 @@ wxWindow* wxPGChoiceEditor::CreateControlsBase( wxPropertyGrid* propGrid,
     si.x -= wxPG_CHOICEXADJUST;
     wxWindow* ctrlParent = propGrid->GetPanel();
 
-    int odcbFlags = extraStyle | wxNO_BORDER | wxTE_PROCESS_ENTER;
+    int odcbFlags = extraStyle | wxBORDER_NONE | wxTE_PROCESS_ENTER;
+
+    if ( (property->GetFlags() & wxPG_PROP_USE_DCC) &&
+         wxDynamicCast(property, wxBoolProperty) )
+        odcbFlags |= wxODCB_DCLICK_CYCLES;
 
     //
     // If common value specified, use appropriate index
     unsigned int cmnVals = property->GetDisplayedCommonValueCount();
     if ( cmnVals )
     {
-        if ( !isUnspecified )
+        if ( !property->IsValueUnspecified() )
         {
             int cmnVal = property->GetCommonValue();
             if ( cmnVal >= 0 )
@@ -1050,31 +1055,30 @@ wxWindow* wxPGChoiceEditor::CreateControlsBase( wxPropertyGrid* propGrid,
                labels,
                odcbFlags);
 
-    //int extRight = propGrid->GetClientSize().x - (po.x+si.x);
-    //int extRight =  - (po.x+si.x);
-
     cb->SetButtonPosition(si.y,0,wxRIGHT);
-    //cb->SetPopupExtents( 1, extRight );
-    cb->SetTextIndent(wxPG_XBEFORETEXT-1);
+    cb->SetMargins(wxPG_XBEFORETEXT-1);
 
-    wxPGChoiceEditor_SetCustomPaintWidth( propGrid, cb, property->GetCommonValue() );
-    /*if ( property->GetFlags() & wxPG_PROP_CUSTOMIMAGE )
-    {
-        wxSize imageSize = propGrid->GetImageSize(property, index);
-        if ( imageSize.x ) imageSize.x += ODCB_CUST_PAINT_MARGIN;
-        cb->SetCustomPaintWidth( imageSize.x );
-    }*/
+    // Set hint text
+    cb->SetHint(property->GetHintText());
+
+    wxPGChoiceEditor_SetCustomPaintWidth( propGrid, cb,
+                                          property->GetCommonValue() );
 
     if ( index >= 0 && index < (int)cb->GetCount() )
     {
         cb->SetSelection( index );
-        if ( defString.length() )
+        if ( !defString.empty() )
             cb->SetText( defString );
     }
-    else if ( !(extraStyle & wxCB_READONLY) && defString.length() )
+    else if ( !(extraStyle & wxCB_READONLY) && !defString.empty() )
+    {
+        propGrid->SetupTextCtrlValue(defString);
         cb->SetValue( defString );
+    }
     else
+    {
         cb->SetSelection( -1 );
+    }
 
 #ifdef __WXMSW__
     cb->Show();
@@ -1088,8 +1092,8 @@ void wxPGChoiceEditor::UpdateControl( wxPGProperty* property, wxWindow* ctrl ) c
 {
     wxASSERT( ctrl );
     wxOwnerDrawnComboBox* cb = (wxOwnerDrawnComboBox*)ctrl;
-    wxASSERT( cb->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)));
-    int ind = property->GetChoiceInfo( (wxPGChoiceInfo*)NULL );
+    wxASSERT( wxDynamicCast(cb, wxOwnerDrawnComboBox));
+    int ind = property->GetChoiceSelection();
     cb->SetSelection(ind);
 }
 
@@ -1104,7 +1108,7 @@ int wxPGChoiceEditor::InsertItem( wxWindow* ctrl, const wxString& label, int ind
 {
     wxASSERT( ctrl );
     wxOwnerDrawnComboBox* cb = (wxOwnerDrawnComboBox*)ctrl;
-    wxASSERT( cb->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)));
+    wxASSERT( wxDynamicCast(cb, wxOwnerDrawnComboBox));
 
     if (index < 0)
         index = cb->GetCount();
@@ -1117,7 +1121,7 @@ void wxPGChoiceEditor::DeleteItem( wxWindow* ctrl, int index ) const
 {
     wxASSERT( ctrl );
     wxOwnerDrawnComboBox* cb = (wxOwnerDrawnComboBox*)ctrl;
-    wxASSERT( cb->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)));
+    wxASSERT( wxDynamicCast(cb, wxOwnerDrawnComboBox));
 
     cb->Delete(index);
 }
@@ -1125,7 +1129,7 @@ void wxPGChoiceEditor::DeleteItem( wxWindow* ctrl, int index ) const
 bool wxPGChoiceEditor::OnEvent( wxPropertyGrid* propGrid, wxPGProperty* property,
     wxWindow* ctrl, wxEvent& event ) const
 {
-    if ( event.GetEventType() == wxEVT_COMMAND_COMBOBOX_SELECTED )
+    if ( event.GetEventType() == wxEVT_COMBOBOX )
     {
         wxPGComboBox* cb = (wxPGComboBox*)ctrl;
         int index = cb->GetSelection();
@@ -1146,11 +1150,16 @@ bool wxPGChoiceEditor::OnEvent( wxPropertyGrid* propGrid, wxPGProperty* property
                     propGrid->SetInternalFlag(wxPG_FL_VALUE_CHANGE_IN_EVENT);
                 property->SetValueToUnspecified();
                 if ( !cb->HasFlag(wxCB_READONLY) )
-                    cb->GetTextCtrl()->SetValue(wxEmptyString);
+                {
+                    wxString unspecValueText;
+                    unspecValueText = propGrid->GetUnspecifiedValueText();
+                    propGrid->SetupTextCtrlValue(unspecValueText);
+                    cb->GetTextCtrl()->SetValue(unspecValueText);
+                }
                 return false;
             }
         }
-        return wxPGChoiceEditor_SetCustomPaintWidth( propGrid, cb, cmnValIndex );        
+        return wxPGChoiceEditor_SetCustomPaintWidth( propGrid, cb, cmnValIndex );
     }
     return false;
 }
@@ -1162,7 +1171,7 @@ bool wxPGChoiceEditor::GetValueFromControl( wxVariant& variant, wxPGProperty* pr
 
     int index = cb->GetSelection();
 
-    if ( index != property->GetChoiceInfo( (wxPGChoiceInfo*) NULL ) ||
+    if ( index != property->GetChoiceSelection() ||
         // Changing unspecified always causes event (returning
         // true here should be enough to trigger it).
          property->IsValueUnspecified()
@@ -1174,10 +1183,13 @@ bool wxPGChoiceEditor::GetValueFromControl( wxVariant& variant, wxPGProperty* pr
 }
 
 
-void wxPGChoiceEditor::SetControlStringValue( wxPGProperty* WXUNUSED(property), wxWindow* ctrl, const wxString& txt ) const
+void wxPGChoiceEditor::SetControlStringValue( wxPGProperty* property,
+                                              wxWindow* ctrl,
+                                              const wxString& txt ) const
 {
     wxOwnerDrawnComboBox* cb = (wxOwnerDrawnComboBox*)ctrl;
     wxASSERT( cb );
+    property->GetGrid()->SetupTextCtrlValue(txt);
     cb->SetValue(txt);
 }
 
@@ -1190,10 +1202,13 @@ void wxPGChoiceEditor::SetControlIntValue( wxPGProperty* WXUNUSED(property), wxW
 }
 
 
-void wxPGChoiceEditor::SetValueToUnspecified( wxPGProperty* WXUNUSED(property), wxWindow* ctrl ) const
+void wxPGChoiceEditor::SetValueToUnspecified( wxPGProperty* WXUNUSED(property),
+                                              wxWindow* ctrl ) const
 {
     wxOwnerDrawnComboBox* cb = (wxOwnerDrawnComboBox*)ctrl;
-    cb->SetSelection(-1);
+
+    if ( cb->HasFlag(wxCB_READONLY) )
+        cb->SetSelection(-1);
 }
 
 
@@ -1203,7 +1218,10 @@ bool wxPGChoiceEditor::CanContainCustomImage() const
 }
 
 
-wxPGChoiceEditor::~wxPGChoiceEditor() { }
+wxPGChoiceEditor::~wxPGChoiceEditor()
+{
+    wxPG_EDITOR(Choice) = NULL;
+}
 
 
 // -----------------------------------------------------------------------
@@ -1211,13 +1229,17 @@ wxPGChoiceEditor::~wxPGChoiceEditor() { }
 // -----------------------------------------------------------------------
 
 
-WX_PG_IMPLEMENT_EDITOR_CLASS(ComboBox,wxPGComboBoxEditor,wxPGChoiceEditor)
+WX_PG_IMPLEMENT_INTERNAL_EDITOR_CLASS(ComboBox,
+                                      wxPGComboBoxEditor,
+                                      wxPGChoiceEditor)
 
 
 void wxPGComboBoxEditor::UpdateControl( wxPGProperty* property, wxWindow* ctrl ) const
 {
     wxOwnerDrawnComboBox* cb = (wxOwnerDrawnComboBox*)ctrl;
-    cb->SetValue(property->GetValueString(wxPG_EDITABLE_VALUE));
+    wxString s = property->GetValueAsString(wxPG_EDITABLE_VALUE);
+    property->GetGrid()->SetupTextCtrlValue(s);
+    cb->SetValue(s);
 
     // TODO: If string matches any selection, then select that.
 }
@@ -1237,8 +1259,8 @@ bool wxPGComboBoxEditor::OnEvent( wxPropertyGrid* propGrid,
                                   wxWindow* ctrl,
                                   wxEvent& event ) const
 {
-    wxOwnerDrawnComboBox* cb = (wxOwnerDrawnComboBox*) NULL;
-    wxWindow* textCtrl = (wxWindow*) NULL;
+    wxOwnerDrawnComboBox* cb = NULL;
+    wxWindow* textCtrl = NULL;
 
     if ( ctrl )
     {
@@ -1258,7 +1280,7 @@ bool wxPGComboBoxEditor::GetValueFromControl( wxVariant& variant, wxPGProperty*
     wxOwnerDrawnComboBox* cb = (wxOwnerDrawnComboBox*)ctrl;
     wxString textVal = cb->GetValue();
 
-    if ( property->UsesAutoUnspecified() && !textVal.length() )
+    if ( property->UsesAutoUnspecified() && textVal.empty() )
     {
         variant.MakeNull();
         return true;
@@ -1275,14 +1297,19 @@ bool wxPGComboBoxEditor::GetValueFromControl( wxVariant& variant, wxPGProperty*
 }
 
 
-void wxPGComboBoxEditor::OnFocus( wxPGProperty*, wxWindow* ctrl ) const
+void wxPGComboBoxEditor::OnFocus( wxPGProperty* property,
+                                  wxWindow* ctrl ) const
 {
     wxOwnerDrawnComboBox* cb = (wxOwnerDrawnComboBox*)ctrl;
-    cb->GetTextCtrl()->SetSelection(-1,-1);
+    wxPGTextCtrlEditor_OnFocus(property, cb->GetTextCtrl());
 }
 
 
-wxPGComboBoxEditor::~wxPGComboBoxEditor() { }
+wxPGComboBoxEditor::~wxPGComboBoxEditor()
+{
+    wxPG_EDITOR(ComboBox) = NULL;
+}
+
 
 
 // -----------------------------------------------------------------------
@@ -1290,8 +1317,9 @@ wxPGComboBoxEditor::~wxPGComboBoxEditor() { }
 // -----------------------------------------------------------------------
 
 
-// This simpler implement_editor macro doesn't define class body.
-WX_PG_IMPLEMENT_EDITOR_CLASS(ChoiceAndButton,wxPGChoiceAndButtonEditor,wxPGChoiceEditor)
+WX_PG_IMPLEMENT_INTERNAL_EDITOR_CLASS(ChoiceAndButton,
+                                      wxPGChoiceAndButtonEditor,
+                                      wxPGChoiceEditor)
 
 
 wxPGWindowList wxPGChoiceAndButtonEditor::CreateControls( wxPropertyGrid* propGrid,
@@ -1322,7 +1350,7 @@ wxPGWindowList wxPGChoiceAndButtonEditor::CreateControls( wxPropertyGrid* propGr
     ch_sz.x -= wxPG_TEXTCTRL_AND_BUTTON_SPACING;
 #endif
 
-    wxWindow* ch = wxPG_EDITOR(Choice)->CreateControls(propGrid,property,
+    wxWindow* ch = wxPGEditor_Choice->CreateControls(propGrid,property,
         pos,ch_sz).m_primary;
 
 #ifdef __WXMSW__
@@ -1333,16 +1361,18 @@ wxPGWindowList wxPGChoiceAndButtonEditor::CreateControls( wxPropertyGrid* propGr
 }
 
 
-wxPGChoiceAndButtonEditor::~wxPGChoiceAndButtonEditor() { }
-
+wxPGChoiceAndButtonEditor::~wxPGChoiceAndButtonEditor()
+{
+    wxPG_EDITOR(ChoiceAndButton) = NULL;
+}
 
 // -----------------------------------------------------------------------
 // wxPGTextCtrlAndButtonEditor
 // -----------------------------------------------------------------------
 
-
-// This simpler implement_editor macro doesn't define class body.
-WX_PG_IMPLEMENT_EDITOR_CLASS(TextCtrlAndButton,wxPGTextCtrlAndButtonEditor,wxPGTextCtrlEditor)
+WX_PG_IMPLEMENT_INTERNAL_EDITOR_CLASS(TextCtrlAndButton,
+                                      wxPGTextCtrlAndButtonEditor,
+                                      wxPGTextCtrlEditor)
 
 
 wxPGWindowList wxPGTextCtrlAndButtonEditor::CreateControls( wxPropertyGrid* propGrid,
@@ -1358,8 +1388,10 @@ wxPGWindowList wxPGTextCtrlAndButtonEditor::CreateControls( wxPropertyGrid* prop
 }
 
 
-wxPGTextCtrlAndButtonEditor::~wxPGTextCtrlAndButtonEditor() { }
-
+wxPGTextCtrlAndButtonEditor::~wxPGTextCtrlAndButtonEditor()
+{
+    wxPG_EDITOR(TextCtrlAndButton) = NULL;
+}
 
 // -----------------------------------------------------------------------
 // wxPGCheckBoxEditor
@@ -1367,20 +1399,39 @@ wxPGTextCtrlAndButtonEditor::~wxPGTextCtrlAndButtonEditor() { }
 
 #if wxPG_INCLUDE_CHECKBOX
 
-WX_PG_IMPLEMENT_EDITOR_CLASS(CheckBox,wxPGCheckBoxEditor,wxPGEditor)
+WX_PG_IMPLEMENT_INTERNAL_EDITOR_CLASS(CheckBox,
+                                      wxPGCheckBoxEditor,
+                                      wxPGEditor)
 
 
-// state argument: 0x01 = set if checked
-//                 0x02 = set if rectangle should be bold
-static void DrawSimpleCheckBox( wxDC& dc, const wxRect& rect, int box_hei, int state, const wxColour& linecol )
+// Check box state flags
+enum
 {
+    wxSCB_STATE_UNCHECKED   = 0,
+    wxSCB_STATE_CHECKED     = 1,
+    wxSCB_STATE_BOLD        = 2,
+    wxSCB_STATE_UNSPECIFIED = 4
+};
+
+const int wxSCB_SETVALUE_CYCLE = 2;
 
+
+static void DrawSimpleCheckBox( wxDC& dc, const wxRect& rect, int box_hei,
+                                int state )
+{
     // Box rectangle.
-    wxRect r(rect.x+wxPG_XBEFORETEXT,rect.y+((rect.height-box_hei)/2),box_hei,box_hei);
+    wxRect r(rect.x+wxPG_XBEFORETEXT,rect.y+((rect.height-box_hei)/2),
+             box_hei,box_hei);
+    wxColour useCol = dc.GetTextForeground();
+
+    if ( state & wxSCB_STATE_UNSPECIFIED )
+    {
+        useCol = wxColour(220, 220, 220);
+    }
 
     // Draw check mark first because it is likely to overdraw the
     // surrounding rectangle.
-    if ( state & 1 )
+    if ( state & wxSCB_STATE_CHECKED )
     {
         wxRect r2(r.x+wxPG_CHECKMARK_XADJ,
                   r.y+wxPG_CHECKMARK_YADJ,
@@ -1394,18 +1445,17 @@ static void DrawSimpleCheckBox( wxDC& dc, const wxRect& rect, int box_hei, int s
         // This would draw a simple cross check mark.
         // dc.DrawLine(r.x,r.y,r.x+r.width-1,r.y+r.height-1);
         // dc.DrawLine(r.x,r.y+r.height-1,r.x+r.width-1,r.y);
-
     }
 
-    if ( !(state & 2) )
+    if ( !(state & wxSCB_STATE_BOLD) )
     {
         // Pen for thin rectangle.
-        dc.SetPen(linecol);
+        dc.SetPen(useCol);
     }
     else
     {
         // Pen for bold rectangle.
-        wxPen linepen(linecol,2,wxSOLID);
+        wxPen linepen(useCol,2,wxSOLID);
         linepen.SetJoin(wxJOIN_MITER); // This prevents round edges.
         dc.SetPen(linepen);
         r.x++;
@@ -1433,198 +1483,155 @@ public:
                       wxWindowID id,
                       const wxPoint& pos = wxDefaultPosition,
                       const wxSize& size = wxDefaultSize )
-        : wxControl(parent,id,pos,size,wxNO_BORDER|wxWANTS_CHARS)
+        : wxControl(parent,id,pos,size,wxBORDER_NONE|wxWANTS_CHARS)
     {
         // Due to SetOwnFont stuff necessary for GTK+ 1.2, we need to have this
         SetFont( parent->GetFont() );
 
         m_state = 0;
-        wxPropertyGrid* pg = (wxPropertyGrid*) parent->GetParent();
-        wxASSERT( pg->IsKindOf(CLASSINFO(wxPropertyGrid)) );
-        m_boxHeight = pg->GetFontHeight();
-        SetBackgroundStyle( wxBG_STYLE_COLOUR );
+        m_boxHeight = 12;
+
+        SetBackgroundStyle( wxBG_STYLE_CUSTOM );
     }
 
     virtual ~wxSimpleCheckBox();
 
-    virtual bool ProcessEvent(wxEvent& event);
-
     int m_state;
     int m_boxHeight;
 
+private:
+    void OnPaint( wxPaintEvent& event );
+    void OnLeftClick( wxMouseEvent& event );
+    void OnKeyDown( wxKeyEvent& event );
+
+    void OnResize( wxSizeEvent& event )
+    {
+        Refresh();
+        event.Skip();
+    }
+
     static wxBitmap* ms_doubleBuffer;
 
+    DECLARE_EVENT_TABLE()
 };
 
+BEGIN_EVENT_TABLE(wxSimpleCheckBox, wxControl)
+    EVT_PAINT(wxSimpleCheckBox::OnPaint)
+    EVT_LEFT_DOWN(wxSimpleCheckBox::OnLeftClick)
+    EVT_LEFT_DCLICK(wxSimpleCheckBox::OnLeftClick)
+    EVT_KEY_DOWN(wxSimpleCheckBox::OnKeyDown)
+    EVT_SIZE(wxSimpleCheckBox::OnResize)
+END_EVENT_TABLE()
+
 wxSimpleCheckBox::~wxSimpleCheckBox()
 {
-    delete ms_doubleBuffer;
-    ms_doubleBuffer = NULL;
+    wxDELETE(ms_doubleBuffer);
 }
 
+wxBitmap* wxSimpleCheckBox::ms_doubleBuffer = NULL;
+
+void wxSimpleCheckBox::OnPaint( wxPaintEvent& WXUNUSED(event) )
+{
+    wxSize clientSize = GetClientSize();
+    wxAutoBufferedPaintDC dc(this);
 
-wxBitmap* wxSimpleCheckBox::ms_doubleBuffer = (wxBitmap*) NULL;
+    dc.Clear();
+    wxRect rect(0,0,clientSize.x,clientSize.y);
+    rect.y += 1;
+    rect.width += 1;
 
-// value = 2 means toggle (sorry, too lazy to do constants)
-void wxSimpleCheckBox::SetValue( int value )
+    wxColour bgcol = GetBackgroundColour();
+    dc.SetBrush( bgcol );
+    dc.SetPen( bgcol );
+    dc.DrawRectangle( rect );
+
+    dc.SetTextForeground(GetForegroundColour());
+
+    int state = m_state;
+    if ( !(state & wxSCB_STATE_UNSPECIFIED) &&
+         GetFont().GetWeight() == wxBOLD )
+        state |= wxSCB_STATE_BOLD;
+
+    DrawSimpleCheckBox(dc, rect, m_boxHeight, state);
+}
+
+void wxSimpleCheckBox::OnLeftClick( wxMouseEvent& event )
 {
-    if ( value > 1 )
+    if ( (event.m_x > (wxPG_XBEFORETEXT-2)) &&
+         (event.m_x <= (wxPG_XBEFORETEXT-2+m_boxHeight)) )
     {
-        m_state++;
-        if ( m_state > 1 ) m_state = 0;
+        SetValue(wxSCB_SETVALUE_CYCLE);
     }
-    else
+}
+
+void wxSimpleCheckBox::OnKeyDown( wxKeyEvent& event )
+{
+    if ( event.GetKeyCode() == WXK_SPACE )
     {
-        m_state = value;
+        SetValue(wxSCB_SETVALUE_CYCLE);
     }
-    Refresh();
-
-    wxCommandEvent evt(wxEVT_COMMAND_CHECKBOX_CLICKED,GetParent()->GetId());
-
-    wxPropertyGrid* propGrid = (wxPropertyGrid*) GetParent()->GetParent();
-    wxASSERT( propGrid->IsKindOf(CLASSINFO(wxPropertyGrid)) );
-    propGrid->OnCustomEditorEvent(evt);
 }
 
-
-bool wxSimpleCheckBox::ProcessEvent(wxEvent& event)
+void wxSimpleCheckBox::SetValue( int value )
 {
-    wxPropertyGrid* propGrid = (wxPropertyGrid*) GetParent()->GetParent();
-    wxASSERT( propGrid->IsKindOf(CLASSINFO(wxPropertyGrid)) );
-
-    if ( event.GetEventType() == wxEVT_NAVIGATION_KEY )
+    if ( value == wxSCB_SETVALUE_CYCLE )
     {
-        //wxLogDebug(wxT("wxEVT_NAVIGATION_KEY"));
-        //SetFocusFromKbd();
-        //event.Skip();
-        //return wxControl::ProcessEvent(event);
+        if ( m_state & wxSCB_STATE_CHECKED )
+            m_state &= ~wxSCB_STATE_CHECKED;
+        else
+            m_state |= wxSCB_STATE_CHECKED;
     }
     else
-    if ( ( (event.GetEventType() == wxEVT_LEFT_DOWN || event.GetEventType() == wxEVT_LEFT_DCLICK)
-          && ((wxMouseEvent&)event).m_x > (wxPG_XBEFORETEXT-2)
-          && ((wxMouseEvent&)event).m_x <= (wxPG_XBEFORETEXT-2+m_boxHeight) )
-       )
     {
-        SetValue(2);
-        return true;
+        m_state = value;
     }
-    else if ( event.GetEventType() == wxEVT_PAINT )
-    {
-        wxSize clientSize = GetClientSize();
-        wxPaintDC dc(this);
-
-        /*
-        // Buffered paint DC doesn't seem to do much good
-        if ( !ms_doubleBuffer ||
-             clientSize.x > ms_doubleBuffer->GetWidth() ||
-             clientSize.y > ms_doubleBuffer->GetHeight() )
-        {
-            delete ms_doubleBuffer;
-            ms_doubleBuffer = new wxBitmap(clientSize.x+25,clientSize.y+25);
-        }
-
-        wxBufferedPaintDC dc(this,*ms_doubleBuffer);
-        */
-
-        wxRect rect(0,0,clientSize.x,clientSize.y);
-        //rect.x -= 1;
-        rect.y += 1;
-        rect.width += 1;
-
-        m_boxHeight = propGrid->GetFontHeight();
-
-        wxColour bgcol = GetBackgroundColour();
-        dc.SetBrush( bgcol );
-        dc.SetPen( bgcol );
-        dc.DrawRectangle( rect );
-
-        wxColour txcol = GetForegroundColour();
-
-        int state = m_state;
-        if ( m_font.GetWeight() == wxBOLD )
-            state |= 2;
-
-        DrawSimpleCheckBox(dc,rect,m_boxHeight,state,txcol);
-
-        // If focused, indicate it somehow.
-        /*
-        if ( wxWindow::FindFocus() == this )
-        {
-            rect.x += 1;
-            rect.width -= 1;
+    Refresh();
 
-            wxPGDrawFocusRect(dc,rect);
-        }
-        */
+    wxCommandEvent evt(wxEVT_CHECKBOX,GetParent()->GetId());
 
-        return true;
-    }
-    else if ( event.GetEventType() == wxEVT_SIZE ||
-              event.GetEventType() == wxEVT_SET_FOCUS ||
-              event.GetEventType() == wxEVT_KILL_FOCUS
-            )
-    {
-        Refresh();
-    }
-    else if ( event.GetEventType() == wxEVT_KEY_DOWN )
-    {
-        wxKeyEvent& keyEv = (wxKeyEvent&) event;
-
-        if ( keyEv.GetKeyCode() == WXK_TAB )
-        {
-            propGrid->SendNavigationKeyEvent( keyEv.ShiftDown()?0:1 );
-            return true;
-        }
-        else
-        if ( keyEv.GetKeyCode() == WXK_SPACE )
-        {
-            SetValue(2);
-            return true;
-        }
-    }
-    return wxControl::ProcessEvent(event);
+    wxPropertyGrid* propGrid = (wxPropertyGrid*) GetParent();
+    wxASSERT( wxDynamicCast(propGrid, wxPropertyGrid) );
+    propGrid->HandleCustomEditorEvent(evt);
 }
 
-
 wxPGWindowList wxPGCheckBoxEditor::CreateControls( wxPropertyGrid* propGrid,
                                                    wxPGProperty* property,
                                                    const wxPoint& pos,
                                                    const wxSize& size ) const
 {
+    if ( property->HasFlag(wxPG_PROP_READONLY) )
+        return NULL;
+
     wxPoint pt = pos;
     pt.x -= wxPG_XBEFOREWIDGET;
     wxSize sz = size;
     sz.x = propGrid->GetFontHeight() + (wxPG_XBEFOREWIDGET*2) + 4;
 
-    wxSimpleCheckBox* cb = new wxSimpleCheckBox(propGrid->GetPanel(),wxPG_SUBID1,pt,sz);
+    wxSimpleCheckBox* cb = new wxSimpleCheckBox(propGrid->GetPanel(),
+                                                wxPG_SUBID1, pt, sz);
 
     cb->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
 
-    cb->Connect( wxPG_SUBID1, wxEVT_LEFT_DOWN,
-            (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction)
-            &wxPropertyGrid::OnCustomEditorEvent, NULL, propGrid );
-
-    cb->Connect( wxPG_SUBID1, wxEVT_LEFT_DCLICK,
-            (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction)
-            &wxPropertyGrid::OnCustomEditorEvent, NULL, propGrid );
+    UpdateControl(property, cb);
 
-    if ( property->GetChoiceInfo((wxPGChoiceInfo*)NULL) &&
-         !property->IsValueUnspecified() )
-        cb->m_state = 1;
-
-    // If mouse cursor was on the item, toggle the value now.
-    if ( propGrid->GetInternalFlags() & wxPG_FL_ACTIVATION_BY_CLICK )
+    if ( !property->IsValueUnspecified() )
     {
-        wxPoint pt = cb->ScreenToClient(::wxGetMousePosition());
-        if ( pt.x <= (wxPG_XBEFORETEXT-2+cb->m_boxHeight) )
+        // If mouse cursor was on the item, toggle the value now.
+        if ( propGrid->GetInternalFlags() & wxPG_FL_ACTIVATION_BY_CLICK )
         {
-            cb->m_state++;
-
-            if ( cb->m_state > 1 )
-                cb->m_state = 0;
-
-            // Makes sure wxPG_EVT_CHANGING etc. is sent for this initial click 
-            propGrid->ChangePropertyValue(property, wxPGVariant_Bool(cb->m_state));
+            wxPoint point = cb->ScreenToClient(::wxGetMousePosition());
+            if ( point.x <= (wxPG_XBEFORETEXT-2+cb->m_boxHeight) )
+            {
+                if ( cb->m_state & wxSCB_STATE_CHECKED )
+                    cb->m_state &= ~wxSCB_STATE_CHECKED;
+                else
+                    cb->m_state |= wxSCB_STATE_CHECKED;
+
+                // Makes sure wxPG_EVT_CHANGING etc. is sent for this initial
+                // click
+                propGrid->ChangePropertyValue(property,
+                                              wxPGVariant_Bool(cb->m_state));
+            }
         }
     }
 
@@ -1633,58 +1640,47 @@ wxPGWindowList wxPGCheckBoxEditor::CreateControls( wxPropertyGrid* propGrid,
     return cb;
 }
 
-/*
-class wxPGCheckBoxRenderer : public wxPGDefaultRenderer
+void wxPGCheckBoxEditor::DrawValue( wxDC& dc, const wxRect& rect,
+                                    wxPGProperty* property,
+                                    const wxString& WXUNUSED(text) ) const
 {
-public:
+    int state = wxSCB_STATE_UNCHECKED;
 
-    virtual void Render( wxDC& dc, const wxRect& rect,
-                         const wxPropertyGrid* WXUNUSED(propertyGrid), wxPGProperty* property,
-                         int WXUNUSED(column), int WXUNUSED(item), int WXUNUSED(flags) ) const
+    if ( !property->IsValueUnspecified() )
     {
-        int state = 0;
-        if ( !(property->GetFlags() & wxPG_PROP_UNSPECIFIED) )
-        {
-            state = ((wxPGProperty*)property)->GetChoiceInfo((wxPGChoiceInfo*)NULL);
-            if ( dc.GetFont().GetWeight() == wxBOLD ) state |= 2;
-        }
-        DrawSimpleCheckBox(dc,rect,dc.GetCharHeight(),state,dc.GetTextForeground());
+        state = property->GetChoiceSelection();
+        if ( dc.GetFont().GetWeight() == wxBOLD )
+            state |= wxSCB_STATE_BOLD;
+    }
+    else
+    {
+        state |= wxSCB_STATE_UNSPECIFIED;
     }
 
-protected:
-};
-
-wxPGCheckBoxRenderer g_wxPGCheckBoxRenderer;
-
-wxPGCellRenderer* wxPGCheckBoxEditor::GetCellRenderer() const
-{
-    return &g_wxPGCheckBoxRenderer;
+    DrawSimpleCheckBox(dc, rect, dc.GetCharHeight(), state);
 }
-*/
 
-void wxPGCheckBoxEditor::DrawValue( wxDC& dc, const wxRect& rect, wxPGProperty* property, const wxString& WXUNUSED(text) ) const
+void wxPGCheckBoxEditor::UpdateControl( wxPGProperty* property,
+                                        wxWindow* ctrl ) const
 {
-    int state = 0;
+    wxSimpleCheckBox* cb = (wxSimpleCheckBox*) ctrl;
+    wxASSERT( cb );
+
     if ( !property->IsValueUnspecified() )
-    {
-        state = property->GetChoiceInfo((wxPGChoiceInfo*)NULL);
-        if ( dc.GetFont().GetWeight() == wxBOLD ) state |= 2;
-    }
-    DrawSimpleCheckBox(dc,rect,dc.GetCharHeight(),state,dc.GetTextForeground());
-}
+        cb->m_state = property->GetChoiceSelection();
+    else
+        cb->m_state = wxSCB_STATE_UNSPECIFIED;
 
-void wxPGCheckBoxEditor::UpdateControl( wxPGProperty* property, wxWindow* ctrl ) const
-{
-    wxASSERT( ctrl );
-    ((wxSimpleCheckBox*)ctrl)->m_state = property->GetChoiceInfo((wxPGChoiceInfo*)NULL);
-    ctrl->Refresh();
-}
+    wxPropertyGrid* propGrid = property->GetGrid();
+    cb->m_boxHeight = propGrid->GetFontHeight();
 
+    cb->Refresh();
+}
 
 bool wxPGCheckBoxEditor::OnEvent( wxPropertyGrid* WXUNUSED(propGrid), wxPGProperty* WXUNUSED(property),
     wxWindow* WXUNUSED(ctrl), wxEvent& event ) const
 {
-    if ( event.GetEventType() == wxEVT_COMMAND_CHECKBOX_CLICKED )
+    if ( event.GetEventType() == wxEVT_CHECKBOX )
     {
         return true;
     }
@@ -1698,7 +1694,7 @@ bool wxPGCheckBoxEditor::GetValueFromControl( wxVariant& variant, wxPGProperty*
 
     int index = cb->m_state;
 
-    if ( index != property->GetChoiceInfo( (wxPGChoiceInfo*) NULL ) ||
+    if ( index != property->GetChoiceSelection() ||
          // Changing unspecified always causes event (returning
          // true here should be enough to trigger it).
          property->IsValueUnspecified()
@@ -1720,13 +1716,15 @@ void wxPGCheckBoxEditor::SetControlIntValue( wxPGProperty* WXUNUSED(property), w
 
 void wxPGCheckBoxEditor::SetValueToUnspecified( wxPGProperty* WXUNUSED(property), wxWindow* ctrl ) const
 {
-    ((wxSimpleCheckBox*)ctrl)->m_state = 0;
+    ((wxSimpleCheckBox*)ctrl)->m_state = wxSCB_STATE_UNSPECIFIED;
     ctrl->Refresh();
 }
 
 
-wxPGCheckBoxEditor::~wxPGCheckBoxEditor() { }
-
+wxPGCheckBoxEditor::~wxPGCheckBoxEditor()
+{
+    wxPG_EDITOR(CheckBox) = NULL;
+}
 
 #endif // wxPG_INCLUDE_CHECKBOX
 
@@ -1739,14 +1737,6 @@ wxWindow* wxPropertyGrid::GetEditorControl() const
     if ( !ctrl )
         return ctrl;
 
-    // If it's clipper window, return its child instead
-#if wxPG_ENABLE_CLIPPER_WINDOW
-    if ( ctrl->IsKindOf(CLASSINFO(wxPGClipperWindow)) )
-    {
-        return ((wxPGClipperWindow*)ctrl)->GetControl();
-    }
-#endif
-
     return ctrl;
 }
 
@@ -1754,12 +1744,11 @@ wxWindow* wxPropertyGrid::GetEditorControl() const
 
 void wxPropertyGrid::CorrectEditorWidgetSizeX()
 {
-    if ( m_selColumn == -1 )
-        return;
-
     int secWid = 0;
-    int newSplitterx = m_pState->DoGetSplitterPosition(m_selColumn-1);
-    int newWidth = newSplitterx + m_pState->m_colWidths[m_selColumn];
+
+    // Use fixed selColumn 1 for main editor widgets
+    int newSplitterx = m_pState->DoGetSplitterPosition(0);
+    int newWidth = newSplitterx + m_pState->m_colWidths[1];
 
     if ( m_wndEditor2 )
     {
@@ -1774,7 +1763,7 @@ void wxPropertyGrid::CorrectEditorWidgetSizeX()
 #ifdef __WXMAC__
         if ( m_wndEditor )
 #else
-        if ( m_wndEditor && m_wndEditor->IsKindOf(CLASSINFO(wxTextCtrl)) )
+        if ( wxDynamicCast(m_wndEditor, wxTextCtrl) )
 #endif
             secWid += wxPG_TEXTCTRL_AND_BUTTON_SPACING;
     }
@@ -1799,57 +1788,52 @@ void wxPropertyGrid::CorrectEditorWidgetSizeX()
 
 void wxPropertyGrid::CorrectEditorWidgetPosY()
 {
-    if ( m_selected && (m_wndEditor || m_wndEditor2) ) 
-    {
-        wxRect r = GetEditorWidgetRect(m_selected, m_selColumn);
+    wxPGProperty* selected = GetSelection();
 
-        if ( m_wndEditor )
+    if ( selected )
+    {
+        if ( m_labelEditor )
         {
-            wxPoint pos = m_wndEditor->GetPosition();
+            wxRect r = GetEditorWidgetRect(selected, m_selColumn);
+            wxPoint pos = m_labelEditor->GetPosition();
 
             // Calculate y offset
             int offset = pos.y % m_lineHeight;
 
-            m_wndEditor->Move(pos.x, r.y + offset);
+            m_labelEditor->Move(pos.x, r.y + offset);
         }
 
-        if ( m_wndEditor2 )
+        if ( m_wndEditor || m_wndEditor2 )
         {
-            wxPoint pos = m_wndEditor2->GetPosition();
+            wxRect r = GetEditorWidgetRect(selected, 1);
 
-            m_wndEditor2->Move(pos.x, r.y);
-        }
-    }
-}
+            if ( m_wndEditor )
+            {
+                wxPoint pos = m_wndEditor->GetPosition();
 
-// -----------------------------------------------------------------------
+                // Calculate y offset
+                int offset = pos.y % m_lineHeight;
 
-bool wxPropertyGrid::AdjustPosForClipperWindow( wxWindow* topCtrlWnd, int* x, int* y )
-{
-#if wxPG_ENABLE_CLIPPER_WINDOW
-    // Take clipper window into account
-    if (topCtrlWnd->GetPosition().x < 1 &&
-        !topCtrlWnd->IsKindOf(CLASSINFO(wxPGClipperWindow)))
-    {
-        topCtrlWnd = topCtrlWnd->GetParent();
-        wxASSERT( topCtrlWnd->IsKindOf(CLASSINFO(wxPGClipperWindow)) );
-        *x -= ((wxPGClipperWindow*)topCtrlWnd)->GetXClip();
-        *y -= ((wxPGClipperWindow*)topCtrlWnd)->GetYClip();
-        return true;
+                m_wndEditor->Move(pos.x, r.y + offset);
+            }
+
+            if ( m_wndEditor2 )
+            {
+                wxPoint pos = m_wndEditor2->GetPosition();
+
+                m_wndEditor2->Move(pos.x, r.y);
+            }
+        }
     }
-#else
-    wxUnusedVar(topCtrlWnd);
-    wxUnusedVar(x);
-    wxUnusedVar(y);
-#endif
-    return false;
 }
 
 // -----------------------------------------------------------------------
 
 // Fixes position of wxTextCtrl-like control (wxSpinCtrl usually
 // fits into that category as well).
-void wxPropertyGrid::FixPosForTextCtrl( wxWindow* ctrl, const wxPoint& offset )
+void wxPropertyGrid::FixPosForTextCtrl( wxWindow* ctrl,
+                                        unsigned int WXUNUSED(forColumn),
+                                        const wxPoint& offset )
 {
     // Center the control vertically
     wxRect finalPos = ctrl->GetRect();
@@ -1862,7 +1846,14 @@ void wxPropertyGrid::FixPosForTextCtrl( wxWindow* ctrl, const wxPoint& offset )
     finalPos.y += y_adj;
     finalPos.height -= (y_adj+sz_dec);
 
-    const int textCtrlXAdjust = wxPG_TEXTCTRLXADJUST;
+#ifndef wxPG_TEXTCTRLXADJUST
+    int textCtrlXAdjust = wxPG_XBEFORETEXT - 1;
+
+    wxTextCtrl* tc = static_cast<wxTextCtrl*>(ctrl);
+    tc->SetMargins(0);
+#else
+    int textCtrlXAdjust = wxPG_TEXTCTRLXADJUST;
+#endif
 
     finalPos.x += textCtrlXAdjust;
     finalPos.width -= textCtrlXAdjust;
@@ -1880,14 +1871,16 @@ wxWindow* wxPropertyGrid::GenerateEditorTextCtrl( const wxPoint& pos,
                                                   const wxString& value,
                                                   wxWindow* secondary,
                                                   int extraStyle,
-                                                  int maxLen )
+                                                  int maxLen,
+                                                  unsigned int forColumn )
 {
-    wxPGProperty* selected = m_selected;
-    wxASSERT(selected);
+    wxWindowID id = wxPG_SUBID1;
+    wxPGProperty* prop = GetSelection();
+    wxASSERT(prop);
 
     int tcFlags = wxTE_PROCESS_ENTER | extraStyle;
 
-    if ( selected->HasFlag(wxPG_PROP_READONLY) )
+    if ( prop->HasFlag(wxPG_PROP_READONLY) && forColumn == 1 )
         tcFlags |= wxTE_READONLY;
 
     wxPoint p(pos.x,pos.y);
@@ -1895,10 +1888,14 @@ wxWindow* wxPropertyGrid::GenerateEditorTextCtrl( const wxPoint& pos,
 
    // Need to reduce width of text control on Mac
 #if defined(__WXMAC__)
-   s.x -= 8;
+    s.x -= 8;
 #endif
 
-     // Take button into acccount
+    // For label editors, trim the size to allow better splitter grabbing
+    if ( forColumn != 1 )
+        s.x -= 2;
+
+    // Take button into acccount
     if ( secondary )
     {
         s.x -= (secondary->GetSize().x + wxPG_TEXTCTRL_AND_BUTTON_SPACING);
@@ -1911,53 +1908,50 @@ wxWindow* wxPropertyGrid::GenerateEditorTextCtrl( const wxPoint& pos,
     if ( (sz.y - m_lineHeight) > 5 )
         hasSpecialSize = true;
 
-#if wxPG_NAT_TEXTCTRL_BORDER_ANY
-
-    // Create clipper window
-    wxPGClipperWindow* wnd = new wxPGClipperWindow();
-#if defined(__WXMSW__)
-    wnd->Hide();
-#endif
-    wnd->Create(GetPanel(),wxPG_SUBID1,p,s);
-
-    // This generates rect of the control inside the clipper window
-    if ( !hasSpecialSize )
-        wnd->GetControlRect(wxPG_NAT_TEXTCTRL_BORDER_X, wxPG_NAT_TEXTCTRL_BORDER_Y, p, s);
-    else
-        wnd->GetControlRect(0, 0, p, s);
-
-    wxWindow* ctrlParent = wnd;
-
-#else
-
     wxWindow* ctrlParent = GetPanel();
 
     if ( !hasSpecialSize )
-        tcFlags |= wxNO_BORDER;
-
-#endif
+        tcFlags |= wxBORDER_NONE;
 
     wxTextCtrl* tc = new wxTextCtrl();
 
-#if defined(__WXMSW__) && !wxPG_NAT_TEXTCTRL_BORDER_ANY
+#if defined(__WXMSW__)
     tc->Hide();
 #endif
     SetupTextCtrlValue(value);
-    tc->Create(ctrlParent,wxPG_SUBID1,value, p, s,tcFlags);
+    tc->Create(ctrlParent,id,value, p, s,tcFlags);
 
-#if wxPG_NAT_TEXTCTRL_BORDER_ANY
-    wxWindow* ed = wnd;
-    wnd->SetControl(tc);
-#else
-    wxWindow* ed = tc;
+#if defined(__WXMSW__)
+    // On Windows, we need to override read-only text ctrl's background
+    // colour to white. One problem with native 'grey' background is that
+    // tc->GetBackgroundColour() doesn't seem to return correct value
+    // for it.
+    if ( tcFlags & wxTE_READONLY )
+    {
+        wxVisualAttributes vattrs = tc->GetDefaultAttributes();
+        tc->SetBackgroundColour(vattrs.colBg);
+    }
 #endif
 
+    // This code is repeated from DoSelectProperty(). However, font boldness
+    // must be set before margin is set up below in FixPosForTextCtrl().
+    if ( forColumn == 1 &&
+         prop->HasFlag(wxPG_PROP_MODIFIED) &&
+         HasFlag(wxPG_BOLD_MODIFIED) )
+         tc->SetFont( m_captionFont );
+
     // Center the control vertically
     if ( !hasSpecialSize )
-        FixPosForTextCtrl(ed);
+        FixPosForTextCtrl(tc, forColumn);
+
+    if ( forColumn != 1 )
+    {
+        tc->SetBackgroundColour(m_colSelBack);
+        tc->SetForegroundColour(m_colSelFore);
+    }
 
 #ifdef __WXMSW__
-    ed->Show();
+    tc->Show();
     if ( secondary )
         secondary->Show();
 #endif
@@ -1966,14 +1960,25 @@ wxWindow* wxPropertyGrid::GenerateEditorTextCtrl( const wxPoint& pos,
     if ( maxLen > 0 )
         tc->SetMaxLength( maxLen );
 
-    return (wxWindow*) ed;
+    wxVariant attrVal = prop->GetAttribute(wxPG_ATTR_AUTOCOMPLETE);
+    if ( !attrVal.IsNull() )
+    {
+        wxASSERT(attrVal.GetType() == wxS("arrstring"));
+        tc->AutoComplete(attrVal.GetArrayString());
+    }
+
+    // Set hint text
+    tc->SetHint(prop->GetHintText());
+
+    return tc;
 }
 
 // -----------------------------------------------------------------------
 
 wxWindow* wxPropertyGrid::GenerateEditorButton( const wxPoint& pos, const wxSize& sz )
 {
-    wxPGProperty* selected = m_selected;
+    wxWindowID id = wxPG_SUBID2;
+    wxPGProperty* selected = GetSelection();
     wxASSERT(selected);
 
 #ifdef __WXMAC__
@@ -1985,13 +1990,13 @@ wxWindow* wxPropertyGrid::GenerateEditorButton( const wxPoint& pos, const wxSize
    wxSize s(25, -1);
 
    wxButton* but = new wxButton();
-   but->Create(GetPanel(),wxPG_SUBID2,wxS("..."),p,s,wxWANTS_CHARS);
+   but->Create(GetPanel(),id,wxS("..."),p,s,wxWANTS_CHARS);
 
    // Now that we know the size, move to the correct position
    p.x = pos.x + sz.x - but->GetSize().x - 2;
    but->Move(p);
 
-#else 
+#else
     wxSize s(sz.y-(wxPG_BUTTON_SIZEDEC*2)+(wxPG_NAT_BUTTON_BORDER_Y*2),
         sz.y-(wxPG_BUTTON_SIZEDEC*2)+(wxPG_NAT_BUTTON_BORDER_Y*2));
 
@@ -1999,16 +2004,28 @@ wxWindow* wxPropertyGrid::GenerateEditorButton( const wxPoint& pos, const wxSize
     if ( s.x > m_lineHeight )
         s.x = m_lineHeight;
 
+#ifdef __WXGTK__
+    // On wxGTK, take fixed button margins into account
+    if ( s.x < 25 )
+        s.x = 25;
+#endif
+
     wxPoint p(pos.x+sz.x-s.x,
         pos.y+wxPG_BUTTON_SIZEDEC-wxPG_NAT_BUTTON_BORDER_Y);
 
     wxButton* but = new wxButton();
-#ifdef __WXMSW__
+  #ifdef __WXMSW__
     but->Hide();
-#endif
-    but->Create(GetPanel(),wxPG_SUBID2,wxS("..."),p,s,wxWANTS_CHARS);
-
-    but->SetFont( m_captionFont );
+  #endif
+    but->Create(GetPanel(),id,wxS("..."),p,s,wxWANTS_CHARS);
+
+  #ifdef __WXGTK__
+    wxFont font = GetFont();
+    font.SetPointSize(font.GetPointSize()-2);
+    but->SetFont(font);
+  #else
+    but->SetFont(GetFont());
+  #endif
 #endif
 
     if ( selected->HasFlag(wxPG_PROP_READONLY) )
@@ -2034,19 +2051,41 @@ wxWindow* wxPropertyGrid::GenerateEditorTextCtrlAndButton( const wxPoint& pos,
         // There is button Show in GenerateEditorTextCtrl as well
         but->Show();
     #endif
-        return (wxWindow*) NULL;
+        return NULL;
     }
 
     wxString text;
 
     if ( !property->IsValueUnspecified() )
-        text = property->GetValueString(property->HasFlag(wxPG_PROP_READONLY)?0:wxPG_EDITABLE_VALUE);
+        text = property->GetValueAsString(property->HasFlag(wxPG_PROP_READONLY)?0:wxPG_EDITABLE_VALUE);
 
     return GenerateEditorTextCtrl(pos,sz,text,but,property->m_maxLen);
 }
 
 // -----------------------------------------------------------------------
 
+void wxPropertyGrid::SetEditorAppearance( const wxPGCell& cell,
+                                          bool unspecified )
+{
+    wxPGProperty* property = GetSelection();
+    if ( !property )
+        return;
+    wxWindow* ctrl = GetEditorControl();
+    if ( !ctrl )
+        return;
+
+    property->GetEditorClass()->SetControlAppearance( this,
+                                                      property,
+                                                      ctrl,
+                                                      cell,
+                                                      m_editorAppearance,
+                                                      unspecified );
+
+    m_editorAppearance = cell;
+}
+
+// -----------------------------------------------------------------------
+
 wxTextCtrl* wxPropertyGrid::GetEditorTextCtrl() const
 {
     wxWindow* wnd = GetEditorControl();
@@ -2054,10 +2093,10 @@ wxTextCtrl* wxPropertyGrid::GetEditorTextCtrl() const
     if ( !wnd )
         return NULL;
 
-    if ( wnd->IsKindOf(CLASSINFO(wxTextCtrl)) )
+    if ( wxDynamicCast(wnd, wxTextCtrl) )
         return wxStaticCast(wnd, wxTextCtrl);
 
-    if ( wnd->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)) )
+    if ( wxDynamicCast(wnd, wxOwnerDrawnComboBox) )
     {
         wxOwnerDrawnComboBox* cb = wxStaticCast(wnd, wxOwnerDrawnComboBox);
         return cb->GetTextCtrl();
@@ -2111,36 +2150,48 @@ wxPGMultiButton::wxPGMultiButton( wxPropertyGrid* pg, const wxSize& sz )
     SetBackgroundColour(pg->GetCellBackgroundColour());
 }
 
-int wxPGMultiButton::GenId( int id ) const
+void wxPGMultiButton::Finalize( wxPropertyGrid* WXUNUSED(propGrid),
+                                const wxPoint& pos )
 {
-    if ( id < -1 )
+    Move( pos.x + m_fullEditorSize.x - m_buttonsWidth, pos.y );
+}
+
+int wxPGMultiButton::GenId( int itemid ) const
+{
+    if ( itemid < -1 )
     {
         if ( m_buttons.size() )
-            id = GetButton(m_buttons.size()-1)->GetId() + 1;
+            itemid = GetButton(m_buttons.size()-1)->GetId() + 1;
         else
-            id = wxPG_SUBID2;
+            itemid = wxPG_SUBID2;
     }
-    return id;
+    return itemid;
 }
 
 #if wxUSE_BMPBUTTON
-void wxPGMultiButton::Add( const wxBitmap& bitmap, int id )
+void wxPGMultiButton::Add( const wxBitmap& bitmap, int itemid )
 {
-    id = GenId(id);
+    itemid = GenId(itemid);
     wxSize sz = GetSize();
-    wxButton* button = new wxBitmapButton( this, id, bitmap, wxPoint(sz.x, 0), wxSize(sz.y, sz.y) );
-    m_buttons.push_back(button);
-    int bw = button->GetSize().x;
-    SetSize(wxSize(sz.x+bw,sz.y));
-    m_buttonsWidth += bw;
+    wxButton* button = new wxBitmapButton( this, itemid, bitmap,
+                                           wxPoint(sz.x, 0),
+                                           wxSize(sz.y, sz.y) );
+    DoAddButton( button, sz );
 }
 #endif
 
-void wxPGMultiButton::Add( const wxString& label, int id )
+void wxPGMultiButton::Add( const wxString& label, int itemid )
 {
-    id = GenId(id);
+    itemid = GenId(itemid);
     wxSize sz = GetSize();
-    wxButton* button = new wxButton( this, id, label, wxPoint(sz.x, 0), wxSize(sz.y, sz.y) );
+    wxButton* button = new wxButton( this, itemid, label, wxPoint(sz.x, 0),
+                                     wxSize(sz.y, sz.y) );
+    DoAddButton( button, sz );
+}
+
+void wxPGMultiButton::DoAddButton( wxWindow* button,
+                                   const wxSize& sz )
+{
     m_buttons.push_back(button);
     int bw = button->GetSize().x;
     SetSize(wxSize(sz.x+bw,sz.y));
@@ -2148,3 +2199,5 @@ void wxPGMultiButton::Add( const wxString& label, int id )
 }
 
 // -----------------------------------------------------------------------
+
+#endif  // wxUSE_PROPGRID