]> git.saurik.com Git - wxWidgets.git/blobdiff - src/propgrid/editors.cpp
No changes, just extract wxCreateHiddenWindow() declaration in a header.
[wxWidgets.git] / src / propgrid / editors.cpp
index 3dfbb8a12c472261d2f73abaaa87098464aa3ea9..97647f7e3093ea0312ca7c0e76a0d82b8cc06ae4 100644 (file)
@@ -6,7 +6,7 @@
 // Created:     2007-04-14
 // RCS-ID:      $Id$
 // Copyright:   (c) Jaakko Salli
 // Created:     2007-04-14
 // RCS-ID:      $Id$
 // Copyright:   (c) Jaakko Salli
-// Licence:     wxWindows license
+// Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
 // For compilers that support precompilation, includes "wx/wx.h".
 /////////////////////////////////////////////////////////////////////////////
 
 // For compilers that support precompilation, includes "wx/wx.h".
 // Number added to image width for SetCustomPaintWidth
 #define ODCB_CUST_PAINT_MARGIN               6
 
 // 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
 
 // to trigger a double-click.
 #define DOUBLE_CLICK_CONVERSION_TRESHOLD        500
 
@@ -169,10 +169,11 @@ wxString wxPGEditor::GetName() const
     return GetClassInfo()->GetClassName();
 }
 
     return GetClassInfo()->GetClassName();
 }
 
-void wxPGEditor::DrawValue( wxDC& dc, const wxRect& rect, wxPGProperty* property, const wxString& text ) const
+void wxPGEditor::DrawValue( wxDC& dc, const wxRect& rect,
+                            wxPGProperty* WXUNUSED(property),
+                            const wxString& text ) const
 {
 {
-    if ( !property->IsValueUnspecified() )
-        dc.DrawText( text, rect.x+wxPG_XBEFORETEXT, rect.y );
+    dc.DrawText( text, rect.x+wxPG_XBEFORETEXT, rect.y );
 }
 
 bool wxPGEditor::GetValueFromControl( wxVariant&, wxPGProperty*, wxWindow* ) const
 }
 
 bool wxPGEditor::GetValueFromControl( wxVariant&, wxPGProperty*, wxWindow* ) const
@@ -206,6 +207,108 @@ void wxPGEditor::OnFocus( wxPGProperty*, wxWindow* ) const
 {
 }
 
 {
 }
 
+void wxPGEditor::SetControlAppearance( wxPropertyGrid* pg,
+                                       wxPGProperty* property,
+                                       wxWindow* ctrl,
+                                       const wxPGCell& cell,
+                                       const wxPGCell& oCell,
+                                       bool unspecified ) const
+{
+    // Get old editor appearance
+    wxTextCtrl* tc = NULL;
+    wxComboCtrl* cb = NULL;
+    if ( ctrl->IsKindOf(CLASSINFO(wxTextCtrl)) )
+    {
+        tc = (wxTextCtrl*) ctrl;
+    }
+    else
+    {
+        if ( ctrl->IsKindOf(CLASSINFO(wxComboCtrl)) )
+        {
+            cb = (wxComboCtrl*) ctrl;
+            tc = cb->GetTextCtrl();
+        }
+    }
+
+    if ( tc || cb )
+    {
+        wxString tcText;
+        bool changeText = false;
+
+        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;
+        }
+
+        if ( changeText )
+        {
+            // This prevents value from being modified
+            if ( tc )
+            {
+                pg->SetupTextCtrlValue(tcText);
+                tc->SetValue(tcText);
+            }
+            else
+            {
+                cb->SetText(tcText);
+            }
+        }
+    }
+
+    // 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();
+
+    // Foreground colour
+    const wxColour& fgCol = cell.GetFgCol();
+    if ( fgCol.IsOk() )
+    {
+        ctrl->SetForegroundColour(fgCol);
+    }
+    else if ( oCell.GetFgCol().IsOk() )
+    {
+        ctrl->SetForegroundColour(vattrs.colFg);
+    }
+
+    // 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);
+    }
+
+    // Also call the old SetValueToUnspecified()
+    if ( unspecified )
+        SetValueToUnspecified(property, ctrl);
+}
+
+void wxPGEditor::SetValueToUnspecified( wxPGProperty* WXUNUSED(property),
+                                        wxWindow* WXUNUSED(ctrl) ) const
+{
+}
 
 bool wxPGEditor::CanContainCustomImage() const
 {
 
 bool wxPGEditor::CanContainCustomImage() const
 {
@@ -232,9 +335,11 @@ wxPGWindowList wxPGTextCtrlEditor::CreateControls( wxPropertyGrid* propGrid,
          property->GetChildCount() )
         return NULL;
 
          property->GetChildCount() )
         return NULL;
 
-    if ( !property->IsValueUnspecified() )
-        text = property->GetValueAsString(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) &&
 
     int flags = 0;
     if ( (property->GetFlags() & wxPG_PROP_PASSWORD) &&
@@ -280,6 +385,9 @@ void wxPGTextCtrlEditor::UpdateControl( wxPGProperty* property, wxWindow* ctrl )
     else
         s = property->GetDisplayedString();
 
     else
         s = property->GetDisplayedString();
 
+    wxPropertyGrid* pg = property->GetGrid();
+
+    pg->SetupTextCtrlValue(s);
     tc->SetValue(s);
 
     //
     tc->SetValue(s);
 
     //
@@ -336,7 +444,7 @@ bool wxPGTextCtrlEditor::GetTextCtrlValueFromControl( wxVariant& variant, wxPGPr
     wxTextCtrl* tc = wxStaticCast(ctrl, wxTextCtrl);
     wxString textVal = tc->GetValue();
 
     wxTextCtrl* tc = wxStaticCast(ctrl, wxTextCtrl);
     wxString textVal = tc->GetValue();
 
-    if ( property->UsesAutoUnspecified() && !textVal.length() )
+    if ( property->UsesAutoUnspecified() && textVal.empty() )
     {
         variant.MakeNull();
         return true;
     {
         variant.MakeNull();
         return true;
@@ -360,17 +468,6 @@ bool wxPGTextCtrlEditor::GetValueFromControl( wxVariant& variant, wxPGProperty*
 }
 
 
 }
 
 
-void wxPGTextCtrlEditor::SetValueToUnspecified( wxPGProperty* property, wxWindow* ctrl ) 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);
-}
-
-
 void wxPGTextCtrlEditor::SetControlStringValue( wxPGProperty* property, wxWindow* ctrl, const wxString& txt ) const
 {
     wxTextCtrl* tc = wxStaticCast(ctrl, wxTextCtrl);
 void wxPGTextCtrlEditor::SetControlStringValue( wxPGProperty* property, wxWindow* ctrl, const wxString& txt ) const
 {
     wxTextCtrl* tc = wxStaticCast(ctrl, wxTextCtrl);
@@ -378,19 +475,44 @@ void wxPGTextCtrlEditor::SetControlStringValue( wxPGProperty* property, wxWindow
     wxPropertyGrid* pg = property->GetGrid();
     wxASSERT(pg);  // Really, property grid should exist if editor does
     if ( pg )
     wxPropertyGrid* pg = property->GetGrid();
     wxASSERT(pg);  // Really, property grid should exist if editor does
     if ( pg )
+    {
+        pg->SetupTextCtrlValue(txt);
         tc->SetValue(txt);
         tc->SetValue(txt);
+    }
 }
 
 
 }
 
 
-void wxPGTextCtrlEditor::OnFocus( wxPGProperty*, wxWindow* wnd ) const
+void wxPGTextCtrlEditor_OnFocus( wxPGProperty* property,
+                                 wxTextCtrl* tc )
 {
 {
-    wxTextCtrl* tc = wxStaticCast(wnd, 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);
+
+    if ( tc->GetValue() != correctText )
+    {
+        property->GetGrid()->SetupTextCtrlValue(correctText);
+        tc->SetValue(correctText);
+    }
 
     tc->SetSelection(-1,-1);
 }
 
 
     tc->SetSelection(-1,-1);
 }
 
+void wxPGTextCtrlEditor::OnFocus( wxPGProperty* property,
+                                  wxWindow* wnd ) const
+{
+    wxTextCtrl* tc = wxStaticCast(wnd, wxTextCtrl);
+    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;
+}
 
 
 // -----------------------------------------------------------------------
 
 
 // -----------------------------------------------------------------------
@@ -543,7 +665,17 @@ public:
                              int flags ) const
     {
         wxPropertyGrid* pg = GetGrid();
                              int flags ) const
     {
         wxPropertyGrid* pg = GetGrid();
-        pg->OnComboItemPaint( 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
     }
 
     virtual wxCoord OnMeasureItem( size_t item ) const
@@ -642,7 +774,7 @@ void wxPropertyGrid::OnComboItemPaint( const wxPGComboBox* pCb,
 
     const wxBitmap* itemBitmap = NULL;
 
 
     const wxBitmap* itemBitmap = NULL;
 
-    if ( item >= 0 && choices.IsOk() && choices.Item(item).GetBitmap().Ok() && comValIndex == -1 )
+    if ( item >= 0 && choices.IsOk() && choices.Item(item).GetBitmap().IsOk() && comValIndex == -1 )
         itemBitmap = &choices.Item(item).GetBitmap();
 
     //
         itemBitmap = &choices.Item(item).GetBitmap();
 
     //
@@ -695,20 +827,48 @@ void wxPropertyGrid::OnComboItemPaint( const wxPGComboBox* pCb,
                    rect.y + 1);
 
         int renderFlags = wxPGCellRenderer::DontUseCellColours;
                    rect.y + 1);
 
         int renderFlags = wxPGCellRenderer::DontUseCellColours;
+        bool useCustomPaintProcedure;
+
+        // 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 ( flags & wxODCB_PAINTING_CONTROL )
 
         if ( flags & wxODCB_PAINTING_CONTROL )
+        {
             renderFlags |= wxPGCellRenderer::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
         else
+        {
             renderFlags |= wxPGCellRenderer::ChoicePopup;
 
             renderFlags |= wxPGCellRenderer::ChoicePopup;
 
-        if ( flags & wxODCB_PAINTING_SELECTED )
-            renderFlags |= wxPGCellRenderer::Selected;
+            // 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 ( 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 ( useCustomPaintProcedure )
         {
             pt.x += wxCC_CUSTOM_IMAGE_MARGIN1;
             wxRect r(pt.x,pt.y,cis.x,cis.y);
         {
             pt.x += wxCC_CUSTOM_IMAGE_MARGIN1;
             wxRect r(pt.x,pt.y,cis.x,cis.y);
@@ -797,6 +957,13 @@ bool wxPGChoiceEditor_SetCustomPaintWidth( wxPropertyGrid* propGrid, wxPGComboBo
     wxSize imageSize;
     bool res;
 
     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
     if ( cmnVal >= 0 )
     {
         // Yes, a common value is being selected
@@ -825,14 +992,21 @@ wxWindow* wxPGChoiceEditor::CreateControlsBase( wxPropertyGrid* propGrid,
                                                 const wxSize& sz,
                                                 long extraStyle ) const
 {
                                                 const wxSize& sz,
                                                 long extraStyle ) const
 {
+    // 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();
 
     const wxPGChoices& choices = property->GetChoices();
     wxString defString;
     int index = property->GetChoiceSelection();
 
-    bool isUnspecified = property->IsValueUnspecified();
-
-    if ( !isUnspecified )
-        defString = property->GetDisplayedString();
+    int argFlags = 0;
+    if ( !property->HasFlag(wxPG_PROP_READONLY) &&
+         !property->IsValueUnspecified() )
+        argFlags |= wxPG_EDITABLE_VALUE;
+    defString = property->GetValueAsString(argFlags);
 
     wxArrayString labels = choices.GetLabels();
 
 
     wxArrayString labels = choices.GetLabels();
 
@@ -858,7 +1032,7 @@ wxWindow* wxPGChoiceEditor::CreateControlsBase( wxPropertyGrid* propGrid,
     unsigned int cmnVals = property->GetDisplayedCommonValueCount();
     if ( cmnVals )
     {
     unsigned int cmnVals = property->GetDisplayedCommonValueCount();
     if ( cmnVals )
     {
-        if ( !isUnspecified )
+        if ( !property->IsValueUnspecified() )
         {
             int cmnVal = property->GetCommonValue();
             if ( cmnVal >= 0 )
         {
             int cmnVal = property->GetCommonValue();
             if ( cmnVal >= 0 )
@@ -887,18 +1061,27 @@ wxWindow* wxPGChoiceEditor::CreateControlsBase( wxPropertyGrid* propGrid,
     cb->SetButtonPosition(si.y,0,wxRIGHT);
     cb->SetMargins(wxPG_XBEFORETEXT-1);
 
     cb->SetButtonPosition(si.y,0,wxRIGHT);
     cb->SetMargins(wxPG_XBEFORETEXT-1);
 
-    wxPGChoiceEditor_SetCustomPaintWidth( propGrid, cb, property->GetCommonValue() );
+    // Set hint text
+    cb->SetHint(property->GetHintText());
+
+    wxPGChoiceEditor_SetCustomPaintWidth( propGrid, cb,
+                                          property->GetCommonValue() );
 
     if ( index >= 0 && index < (int)cb->GetCount() )
     {
         cb->SetSelection( index );
 
     if ( index >= 0 && index < (int)cb->GetCount() )
     {
         cb->SetSelection( index );
-        if ( defString.length() )
+        if ( !defString.empty() )
             cb->SetText( defString );
     }
             cb->SetText( defString );
     }
-    else if ( !(extraStyle & wxCB_READONLY) && defString.length() )
+    else if ( !(extraStyle & wxCB_READONLY) && !defString.empty() )
+    {
+        propGrid->SetupTextCtrlValue(defString);
         cb->SetValue( defString );
         cb->SetValue( defString );
+    }
     else
     else
+    {
         cb->SetSelection( -1 );
         cb->SetSelection( -1 );
+    }
 
 #ifdef __WXMSW__
     cb->Show();
 
 #ifdef __WXMSW__
     cb->Show();
@@ -970,7 +1153,12 @@ bool wxPGChoiceEditor::OnEvent( wxPropertyGrid* propGrid, wxPGProperty* property
                     propGrid->SetInternalFlag(wxPG_FL_VALUE_CHANGE_IN_EVENT);
                 property->SetValueToUnspecified();
                 if ( !cb->HasFlag(wxCB_READONLY) )
                     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 false;
             }
         }
@@ -998,10 +1186,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 );
 {
     wxOwnerDrawnComboBox* cb = (wxOwnerDrawnComboBox*)ctrl;
     wxASSERT( cb );
+    property->GetGrid()->SetupTextCtrlValue(txt);
     cb->SetValue(txt);
 }
 
     cb->SetValue(txt);
 }
 
@@ -1014,10 +1205,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;
 {
     wxOwnerDrawnComboBox* cb = (wxOwnerDrawnComboBox*)ctrl;
-    cb->SetSelection(-1);
+
+    if ( cb->HasFlag(wxCB_READONLY) )
+        cb->SetSelection(-1);
 }
 
 
 }
 
 
@@ -1027,7 +1221,10 @@ bool wxPGChoiceEditor::CanContainCustomImage() const
 }
 
 
 }
 
 
-wxPGChoiceEditor::~wxPGChoiceEditor() { }
+wxPGChoiceEditor::~wxPGChoiceEditor()
+{
+    wxPG_EDITOR(Choice) = NULL;
+}
 
 
 // -----------------------------------------------------------------------
 
 
 // -----------------------------------------------------------------------
@@ -1043,7 +1240,9 @@ WX_PG_IMPLEMENT_INTERNAL_EDITOR_CLASS(ComboBox,
 void wxPGComboBoxEditor::UpdateControl( wxPGProperty* property, wxWindow* ctrl ) const
 {
     wxOwnerDrawnComboBox* cb = (wxOwnerDrawnComboBox*)ctrl;
 void wxPGComboBoxEditor::UpdateControl( wxPGProperty* property, wxWindow* ctrl ) const
 {
     wxOwnerDrawnComboBox* cb = (wxOwnerDrawnComboBox*)ctrl;
-    cb->SetValue(property->GetValueAsString(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.
 }
 
     // TODO: If string matches any selection, then select that.
 }
@@ -1084,7 +1283,7 @@ bool wxPGComboBoxEditor::GetValueFromControl( wxVariant& variant, wxPGProperty*
     wxOwnerDrawnComboBox* cb = (wxOwnerDrawnComboBox*)ctrl;
     wxString textVal = cb->GetValue();
 
     wxOwnerDrawnComboBox* cb = (wxOwnerDrawnComboBox*)ctrl;
     wxString textVal = cb->GetValue();
 
-    if ( property->UsesAutoUnspecified() && !textVal.length() )
+    if ( property->UsesAutoUnspecified() && textVal.empty() )
     {
         variant.MakeNull();
         return true;
     {
         variant.MakeNull();
         return true;
@@ -1101,14 +1300,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;
 {
     wxOwnerDrawnComboBox* cb = (wxOwnerDrawnComboBox*)ctrl;
-    cb->GetTextCtrl()->SetSelection(-1,-1);
+    wxPGTextCtrlEditor_OnFocus(property, cb->GetTextCtrl());
 }
 
 
 }
 
 
-wxPGComboBoxEditor::~wxPGComboBoxEditor() { }
+wxPGComboBoxEditor::~wxPGComboBoxEditor()
+{
+    wxPG_EDITOR(ComboBox) = NULL;
+}
+
 
 
 // -----------------------------------------------------------------------
 
 
 // -----------------------------------------------------------------------
@@ -1160,8 +1364,10 @@ wxPGWindowList wxPGChoiceAndButtonEditor::CreateControls( wxPropertyGrid* propGr
 }
 
 
 }
 
 
-wxPGChoiceAndButtonEditor::~wxPGChoiceAndButtonEditor() { }
-
+wxPGChoiceAndButtonEditor::~wxPGChoiceAndButtonEditor()
+{
+    wxPG_EDITOR(ChoiceAndButton) = NULL;
+}
 
 // -----------------------------------------------------------------------
 // wxPGTextCtrlAndButtonEditor
 
 // -----------------------------------------------------------------------
 // wxPGTextCtrlAndButtonEditor
@@ -1185,8 +1391,10 @@ wxPGWindowList wxPGTextCtrlAndButtonEditor::CreateControls( wxPropertyGrid* prop
 }
 
 
 }
 
 
-wxPGTextCtrlAndButtonEditor::~wxPGTextCtrlAndButtonEditor() { }
-
+wxPGTextCtrlAndButtonEditor::~wxPGTextCtrlAndButtonEditor()
+{
+    wxPG_EDITOR(TextCtrlAndButton) = NULL;
+}
 
 // -----------------------------------------------------------------------
 // wxPGCheckBoxEditor
 
 // -----------------------------------------------------------------------
 // wxPGCheckBoxEditor
@@ -1212,12 +1420,12 @@ const int wxSCB_SETVALUE_CYCLE = 2;
 
 
 static void DrawSimpleCheckBox( wxDC& dc, const wxRect& rect, int box_hei,
 
 
 static void DrawSimpleCheckBox( wxDC& dc, const wxRect& rect, int box_hei,
-                                int state, const wxColour& lineCol )
+                                int state )
 {
     // Box rectangle.
     wxRect r(rect.x+wxPG_XBEFORETEXT,rect.y+((rect.height-box_hei)/2),
              box_hei,box_hei);
 {
     // Box rectangle.
     wxRect r(rect.x+wxPG_XBEFORETEXT,rect.y+((rect.height-box_hei)/2),
              box_hei,box_hei);
-    wxColour useCol = lineCol;
+    wxColour useCol = dc.GetTextForeground();
 
     if ( state & wxSCB_STATE_UNSPECIFIED )
     {
 
     if ( state & wxSCB_STATE_UNSPECIFIED )
     {
@@ -1320,8 +1528,7 @@ END_EVENT_TABLE()
 
 wxSimpleCheckBox::~wxSimpleCheckBox()
 {
 
 wxSimpleCheckBox::~wxSimpleCheckBox()
 {
-    delete ms_doubleBuffer;
-    ms_doubleBuffer = NULL;
+    wxDELETE(ms_doubleBuffer);
 }
 
 wxBitmap* wxSimpleCheckBox::ms_doubleBuffer = NULL;
 }
 
 wxBitmap* wxSimpleCheckBox::ms_doubleBuffer = NULL;
@@ -1341,14 +1548,14 @@ void wxSimpleCheckBox::OnPaint( wxPaintEvent& WXUNUSED(event) )
     dc.SetPen( bgcol );
     dc.DrawRectangle( rect );
 
     dc.SetPen( bgcol );
     dc.DrawRectangle( rect );
 
-    wxColour txcol = GetForegroundColour();
+    dc.SetTextForeground(GetForegroundColour());
 
     int state = m_state;
     if ( !(state & wxSCB_STATE_UNSPECIFIED) &&
          GetFont().GetWeight() == wxBOLD )
         state |= wxSCB_STATE_BOLD;
 
 
     int state = m_state;
     if ( !(state & wxSCB_STATE_UNSPECIFIED) &&
          GetFont().GetWeight() == wxBOLD )
         state |= wxSCB_STATE_BOLD;
 
-    DrawSimpleCheckBox(dc,rect,m_boxHeight,state,txcol);
+    DrawSimpleCheckBox(dc, rect, m_boxHeight, state);
 }
 
 void wxSimpleCheckBox::OnLeftClick( wxMouseEvent& event )
 }
 
 void wxSimpleCheckBox::OnLeftClick( wxMouseEvent& event )
@@ -1395,6 +1602,9 @@ wxPGWindowList wxPGCheckBoxEditor::CreateControls( wxPropertyGrid* propGrid,
                                                    const wxPoint& pos,
                                                    const wxSize& size ) const
 {
                                                    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;
     wxPoint pt = pos;
     pt.x -= wxPG_XBEFOREWIDGET;
     wxSize sz = size;
@@ -1438,7 +1648,6 @@ void wxPGCheckBoxEditor::DrawValue( wxDC& dc, const wxRect& rect,
                                     const wxString& WXUNUSED(text) ) const
 {
     int state = wxSCB_STATE_UNCHECKED;
                                     const wxString& WXUNUSED(text) ) const
 {
     int state = wxSCB_STATE_UNCHECKED;
-    wxColour rectCol = dc.GetTextForeground();
 
     if ( !property->IsValueUnspecified() )
     {
 
     if ( !property->IsValueUnspecified() )
     {
@@ -1451,7 +1660,7 @@ void wxPGCheckBoxEditor::DrawValue( wxDC& dc, const wxRect& rect,
         state |= wxSCB_STATE_UNSPECIFIED;
     }
 
         state |= wxSCB_STATE_UNSPECIFIED;
     }
 
-    DrawSimpleCheckBox(dc, rect, dc.GetCharHeight(), state, rectCol);
+    DrawSimpleCheckBox(dc, rect, dc.GetCharHeight(), state);
 }
 
 void wxPGCheckBoxEditor::UpdateControl( wxPGProperty* property,
 }
 
 void wxPGCheckBoxEditor::UpdateControl( wxPGProperty* property,
@@ -1515,8 +1724,10 @@ void wxPGCheckBoxEditor::SetValueToUnspecified( wxPGProperty* WXUNUSED(property)
 }
 
 
 }
 
 
-wxPGCheckBoxEditor::~wxPGCheckBoxEditor() { }
-
+wxPGCheckBoxEditor::~wxPGCheckBoxEditor()
+{
+    wxPG_EDITOR(CheckBox) = NULL;
+}
 
 #endif // wxPG_INCLUDE_CHECKBOX
 
 
 #endif // wxPG_INCLUDE_CHECKBOX
 
@@ -1537,8 +1748,10 @@ wxWindow* wxPropertyGrid::GetEditorControl() const
 void wxPropertyGrid::CorrectEditorWidgetSizeX()
 {
     int secWid = 0;
 void wxPropertyGrid::CorrectEditorWidgetSizeX()
 {
     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 )
     {
 
     if ( m_wndEditor2 )
     {
@@ -1578,25 +1791,41 @@ void wxPropertyGrid::CorrectEditorWidgetSizeX()
 
 void wxPropertyGrid::CorrectEditorWidgetPosY()
 {
 
 void wxPropertyGrid::CorrectEditorWidgetPosY()
 {
-    if ( GetSelection() && (m_wndEditor || m_wndEditor2) )
-    {
-        wxRect r = GetEditorWidgetRect(GetSelection(), 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;
 
 
             // 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);
+
+            if ( m_wndEditor )
+            {
+                wxPoint pos = m_wndEditor->GetPosition();
 
 
-            m_wndEditor2->Move(pos.x, r.y);
+                // Calculate y offset
+                int offset = pos.y % m_lineHeight;
+
+                m_wndEditor->Move(pos.x, r.y + offset);
+            }
+
+            if ( m_wndEditor2 )
+            {
+                wxPoint pos = m_wndEditor2->GetPosition();
+
+                m_wndEditor2->Move(pos.x, r.y);
+            }
         }
     }
 }
         }
     }
 }
@@ -1707,6 +1936,13 @@ wxWindow* wxPropertyGrid::GenerateEditorTextCtrl( const wxPoint& pos,
     }
 #endif
 
     }
 #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(tc, forColumn);
     // Center the control vertically
     if ( !hasSpecialSize )
         FixPosForTextCtrl(tc, forColumn);
@@ -1734,6 +1970,9 @@ wxWindow* wxPropertyGrid::GenerateEditorTextCtrl( const wxPoint& pos,
         tc->AutoComplete(attrVal.GetArrayString());
     }
 
         tc->AutoComplete(attrVal.GetArrayString());
     }
 
+    // Set hint text
+    tc->SetHint(prop->GetHintText());
+
     return tc;
 }
 
     return tc;
 }
 
@@ -1828,6 +2067,28 @@ wxWindow* wxPropertyGrid::GenerateEditorTextCtrlAndButton( const wxPoint& pos,
 
 // -----------------------------------------------------------------------
 
 
 // -----------------------------------------------------------------------
 
+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();
 wxTextCtrl* wxPropertyGrid::GetEditorTextCtrl() const
 {
     wxWindow* wnd = GetEditorControl();
@@ -1898,35 +2159,35 @@ void wxPGMultiButton::Finalize( wxPropertyGrid* WXUNUSED(propGrid),
     Move( pos.x + m_fullEditorSize.x - m_buttonsWidth, pos.y );
 }
 
     Move( pos.x + m_fullEditorSize.x - m_buttonsWidth, pos.y );
 }
 
-int wxPGMultiButton::GenId( int id ) const
+int wxPGMultiButton::GenId( int itemid ) const
 {
 {
-    if ( id < -1 )
+    if ( itemid < -1 )
     {
         if ( m_buttons.size() )
     {
         if ( m_buttons.size() )
-            id = GetButton(m_buttons.size()-1)->GetId() + 1;
+            itemid = GetButton(m_buttons.size()-1)->GetId() + 1;
         else
         else
-            id = wxPG_SUBID2;
+            itemid = wxPG_SUBID2;
     }
     }
-    return id;
+    return itemid;
 }
 
 #if wxUSE_BMPBUTTON
 }
 
 #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();
     wxSize sz = GetSize();
-    wxButton* button = new wxBitmapButton( this, id, bitmap,
+    wxButton* button = new wxBitmapButton( this, itemid, bitmap,
                                            wxPoint(sz.x, 0),
                                            wxSize(sz.y, sz.y) );
     DoAddButton( button, sz );
 }
 #endif
 
                                            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();
     wxSize sz = GetSize();
-    wxButton* button = new wxButton( this, id, label, wxPoint(sz.x, 0),
+    wxButton* button = new wxButton( this, itemid, label, wxPoint(sz.x, 0),
                                      wxSize(sz.y, sz.y) );
     DoAddButton( button, sz );
 }
                                      wxSize(sz.y, sz.y) );
     DoAddButton( button, sz );
 }