]> git.saurik.com Git - wxWidgets.git/blobdiff - src/propgrid/propgrid.cpp
Added wxChoice renderer to wxDataViewCtrl
[wxWidgets.git] / src / propgrid / propgrid.cpp
index 61bb108e4c79875d6c1a0d2a859711ce1a648f49..40e2383b6b6724654d0dce502f1e80a8d73ef0ec 100644 (file)
@@ -134,7 +134,7 @@ void wxPropertyGrid::AutoGetTranslation ( bool ) { }
 
 // -----------------------------------------------------------------------
 
-const wxChar *wxPropertyGridNameStr = wxT("wxPropertyGrid");
+const char wxPropertyGridNameStr[] = "wxPropertyGrid";
 
 // -----------------------------------------------------------------------
 // Statics in one class for easy destruction.
@@ -231,90 +231,6 @@ void wxPropertyGridInitGlobalsIfNeeded()
 {
 }
 
-// -----------------------------------------------------------------------
-// wxPGBrush
-// -----------------------------------------------------------------------
-
-//
-// This class is a wxBrush derivative used in the background colour
-// brush cache. It adds wxPG-type colour-in-long to the class.
-// JMS: Yes I know wxBrush doesn't actually hold the value (refcounted
-//   object does), but this is simpler implementation and equally
-//   effective.
-//
-
-class wxPGBrush : public wxBrush
-{
-public:
-    wxPGBrush( const wxColour& colour );
-    wxPGBrush();
-    virtual ~wxPGBrush() { }
-    void SetColour2( const wxColour& colour );
-    inline long GetColourAsLong() const { return m_colAsLong; }
-private:
-    long    m_colAsLong;
-};
-
-
-void wxPGBrush::SetColour2( const wxColour& colour )
-{
-    wxBrush::SetColour(colour);
-    m_colAsLong = wxPG_COLOUR(colour.Red(),colour.Green(),colour.Blue());
-}
-
-
-wxPGBrush::wxPGBrush() : wxBrush()
-{
-    m_colAsLong = 0;
-}
-
-
-wxPGBrush::wxPGBrush( const wxColour& colour ) : wxBrush(colour)
-{
-    m_colAsLong = wxPG_COLOUR(colour.Red(),colour.Green(),colour.Blue());
-}
-
-
-// -----------------------------------------------------------------------
-// wxPGColour
-// -----------------------------------------------------------------------
-
-//
-// Same as wxPGBrush, but for wxColour instead.
-//
-
-class wxPGColour : public wxColour
-{
-public:
-    wxPGColour( const wxColour& colour );
-    wxPGColour();
-    virtual ~wxPGColour() { }
-    void SetColour2( const wxColour& colour );
-    inline long GetColourAsLong() const { return m_colAsLong; }
-private:
-    long    m_colAsLong;
-};
-
-
-void wxPGColour::SetColour2( const wxColour& colour )
-{
-    *this = colour;
-    m_colAsLong = wxPG_COLOUR(colour.Red(),colour.Green(),colour.Blue());
-}
-
-
-wxPGColour::wxPGColour() : wxColour()
-{
-    m_colAsLong = 0;
-}
-
-
-wxPGColour::wxPGColour( const wxColour& colour ) : wxColour(colour)
-{
-    m_colAsLong = wxPG_COLOUR(colour.Red(),colour.Green(),colour.Blue());
-}
-
-
 // -----------------------------------------------------------------------
 // wxPGTLWHandler
 //   Intercepts Close-events sent to wxPropertyGrid's top-level parent,
@@ -409,11 +325,11 @@ protected:
     }
 
     void OnPaint( wxPaintEvent& event );
-    
+
     // Always be focussable, even with child windows
     virtual void SetCanFocus(bool WXUNUSED(canFocus))
     {  wxPanel::SetCanFocus(true); }
-    
+
 
 private:
     DECLARE_EVENT_TABLE()
@@ -493,7 +409,7 @@ wxPropertyGrid::wxPropertyGrid( wxWindow *parent,
                                 const wxPoint& pos,
                                 const wxSize& size,
                                 long style,
-                                const wxChar* name )
+                                const wxString& name )
     : wxScrolledWindow()
 {
     Init1();
@@ -507,7 +423,7 @@ bool wxPropertyGrid::Create( wxWindow *parent,
                              const wxPoint& pos,
                              const wxSize& size,
                              long style,
-                             const wxChar* name )
+                             const wxString& name )
 {
 
     if ( !(style&wxBORDER_MASK) )
@@ -610,7 +526,7 @@ void wxPropertyGrid::Init2()
 #ifdef __WXMAC__
    // Smaller controls on Mac
    SetWindowVariant(wxWINDOW_VARIANT_SMALL);
-#endif 
+#endif
 
     // Now create state, if one didn't exist already
     // (wxPropertyGridManager might have created it for us).
@@ -656,15 +572,14 @@ void wxPropertyGrid::Init2()
         wxScrolledWindow::SetOwnFont( useFont );
     }
     else
+    {
         // This should be otherwise called by SetOwnFont
            CalculateFontAndBitmapStuff( wxPG_DEFAULT_VSPACING );
+    }
 
-    // Add base brush item
-    m_arrBgBrushes.Add((void*)new wxPGBrush());
-
-    // Add base colour items
-    m_arrFgCols.Add((void*)new wxPGColour());
-    m_arrFgCols.Add((void*)new wxPGColour());
+    // Allocate cell datas indirectly by calling setter
+    m_propertyDefaultCell.SetBgCol(*wxBLACK);
+    m_categoryDefaultCell.SetBgCol(*wxBLACK);
 
     RegainColours();
 
@@ -739,18 +654,6 @@ wxPropertyGrid::~wxPropertyGrid()
        delete m_collbmp;
 #endif
 
-    // Delete cached text colours.
-    for ( i=0; i<m_arrFgCols.size(); i++ )
-    {
-        delete (wxPGColour*)m_arrFgCols.Item(i);
-    }
-
-    // Delete cached brushes.
-    for ( i=0; i<m_arrBgBrushes.size(); i++ )
-    {
-        delete (wxPGBrush*)m_arrBgBrushes.Item(i);
-    }
-
     // Delete common value records
     for ( i=0; i<m_commonValues.size(); i++ )
     {
@@ -1072,6 +975,7 @@ void wxPropertyGrid::RegainColours()
             m_colCapBack = wxPGAdjustColour(col,-colDec);
         else
             m_colCapBack = col;
+        m_categoryDefaultCell.GetData()->SetBgCol(m_colCapBack);
     }
 
     if ( !(m_coloursCustomized & 0x0001) )
@@ -1086,27 +990,21 @@ void wxPropertyGrid::RegainColours()
     #endif
         wxColour capForeCol = wxPGAdjustColour(m_colCapBack,colDec,5000,5000,true);
         m_colCapFore = capForeCol;
-
-        // Set the cached colour as well.
-        ((wxPGColour*)m_arrFgCols.Item(1))->SetColour2(capForeCol);
+        m_categoryDefaultCell.GetData()->SetFgCol(capForeCol);
     }
 
     if ( !(m_coloursCustomized & 0x0008) )
     {
         wxColour bgCol = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW );
         m_colPropBack = bgCol;
-
-        // Set the cached brush as well.
-        ((wxPGBrush*)m_arrBgBrushes.Item(0))->SetColour2(bgCol);
+        m_propertyDefaultCell.GetData()->SetBgCol(bgCol);
     }
 
     if ( !(m_coloursCustomized & 0x0010) )
     {
         wxColour fgCol = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT );
         m_colPropFore = fgCol;
-
-        // Set the cached colour as well.
-        ((wxPGColour*)m_arrFgCols.Item(0))->SetColour2(fgCol);
+        m_propertyDefaultCell.GetData()->SetFgCol(fgCol);
     }
 
     if ( !(m_coloursCustomized & 0x0020) )
@@ -1140,13 +1038,7 @@ void wxPropertyGrid::ResetColours()
 bool wxPropertyGrid::SetFont( const wxFont& font )
 {
     // Must disable active editor.
-    if ( m_selected )
-    {
-        bool selRes = ClearSelection();
-        wxPG_CHECK_MSG_DBG( selRes,
-                            false,
-                            wxT("failed to deselect a property (editor probably had invalid value)") );
-    }
+    ClearSelection(false);
 
     // TODO: Following code is disabled with wxMac because
     //   it is reported to fail. I (JMS) cannot debug it
@@ -1201,8 +1093,7 @@ void wxPropertyGrid::SetCellBackgroundColour( const wxColour& col )
     m_colPropBack = col;
     m_coloursCustomized |= 0x08;
 
-    // Set the cached brush as well.
-    ((wxPGBrush*)m_arrBgBrushes.Item(0))->SetColour2(col);
+    m_propertyDefaultCell.GetData()->SetBgCol(col);
 
     Refresh();
 }
@@ -1214,8 +1105,7 @@ void wxPropertyGrid::SetCellTextColour( const wxColour& col )
     m_colPropFore = col;
     m_coloursCustomized |= 0x10;
 
-    // Set the cached colour as well.
-    ((wxPGColour*)m_arrFgCols.Item(0))->SetColour2(col);
+    m_propertyDefaultCell.GetData()->SetFgCol(col);
 
     Refresh();
 }
@@ -1262,6 +1152,9 @@ void wxPropertyGrid::SetCaptionBackgroundColour( const wxColour& col )
 {
     m_colCapBack = col;
     m_coloursCustomized |= 0x02;
+
+    m_categoryDefaultCell.GetData()->SetBgCol(col);
+
     Refresh();
 }
 
@@ -1272,161 +1165,11 @@ void wxPropertyGrid::SetCaptionTextColour( const wxColour& col )
     m_colCapFore = col;
     m_coloursCustomized |= 0x04;
 
-    // Set the cached colour as well.
-    ((wxPGColour*)m_arrFgCols.Item(1))->SetColour2(col);
+    m_categoryDefaultCell.GetData()->SetFgCol(col);
 
     Refresh();
 }
 
-// -----------------------------------------------------------------------
-
-void wxPropertyGrid::SetBackgroundColourIndex( wxPGProperty* p, int index )
-{
-    unsigned char ind = index;
-
-    p->m_bgColIndex = ind;
-
-    unsigned int i;
-    for ( i=0; i<p->GetChildCount(); i++ )
-        SetBackgroundColourIndex(p->Item(i),index);
-}
-
-// -----------------------------------------------------------------------
-
-void wxPropertyGrid::SetPropertyBackgroundColour( wxPGPropArg id, const wxColour& colour )
-{
-    wxPG_PROP_ARG_CALL_PROLOG()
-
-    size_t i;
-    int colInd = -1;
-
-    long colAsLong = wxPG_COLOUR(colour.Red(),colour.Green(),colour.Blue());
-
-    // As it is most likely that the previous colour is used, start comparison
-    // from the end.
-    for ( i=(m_arrBgBrushes.size()-1); i>0; i-- )
-    {
-        if ( ((wxPGBrush*)m_arrBgBrushes.Item(i))->GetColourAsLong() == colAsLong )
-        {
-            colInd = i;
-            break;
-        }
-    }
-
-    if ( colInd < 0 )
-    {
-        colInd = m_arrBgBrushes.size();
-        wxCHECK_RET( colInd < 256, wxT("wxPropertyGrid: Warning - Only 255 different property background colours allowed.") );
-        m_arrBgBrushes.Add( (void*)new wxPGBrush(colour) );
-    }
-
-    // Set indexes
-    SetBackgroundColourIndex(p,colInd);
-
-    // If this was on a visible grid, then draw it.
-    DrawItemAndChildren(p);
-}
-
-// -----------------------------------------------------------------------
-
-wxColour wxPropertyGrid::GetPropertyBackgroundColour( wxPGPropArg id ) const
-{
-    wxPG_PROP_ARG_CALL_PROLOG_RETVAL(wxColour())
-
-    return ((wxPGBrush*)m_arrBgBrushes.Item(p->m_bgColIndex))->GetColour();
-}
-
-// -----------------------------------------------------------------------
-
-void wxPropertyGrid::SetTextColourIndex( wxPGProperty* p, int index, int flags )
-{
-    unsigned char ind = index;
-
-    p->m_fgColIndex = ind;
-
-    if ( p->GetChildCount() && (flags & wxPG_RECURSE) )
-    {
-        unsigned int i;
-        for ( i=0; i<p->GetChildCount(); i++ )
-            SetTextColourIndex( p->Item(i), index, flags );
-    }
-}
-
-// -----------------------------------------------------------------------
-
-int wxPropertyGrid::CacheColour( const wxColour& colour )
-{
-    unsigned int i;
-    int colInd = -1;
-
-    long colAsLong = wxPG_COLOUR(colour.Red(),colour.Green(),colour.Blue());
-
-    // As it is most likely that the previous colour is used, start comparison
-    // from the end.
-    for ( i=(m_arrFgCols.size()-1); i>0; i-- )
-    {
-        if ( ((wxPGColour*)m_arrFgCols.Item(i))->GetColourAsLong() == colAsLong )
-        {
-            colInd = i;
-            break;
-        }
-    }
-
-    if ( colInd < 0 )
-    {
-        colInd = m_arrFgCols.size();
-        wxCHECK_MSG( colInd < 256, 0, wxT("wxPropertyGrid: Warning - Only 255 different property foreground colours allowed.") );
-        m_arrFgCols.Add( (void*)new wxPGColour(colour) );
-    }
-
-    return colInd;
-}
-
-// -----------------------------------------------------------------------
-
-void wxPropertyGrid::SetPropertyTextColour( wxPGPropArg id, const wxColour& colour,
-                                            bool recursively )
-{
-    wxPG_PROP_ARG_CALL_PROLOG()
-
-    if ( p->IsCategory() )
-    {
-        wxPropertyCategory* cat = (wxPropertyCategory*) p;
-        cat->SetTextColIndex(CacheColour(colour));
-    }
-
-    // Set indexes
-    int flags = 0;
-    if ( recursively )
-        flags |= wxPG_RECURSE;
-    SetTextColourIndex(p, CacheColour(colour), flags);
-
-    DrawItemAndChildren(p);
-}
-
-// -----------------------------------------------------------------------
-
-wxColour wxPropertyGrid::GetPropertyTextColour( wxPGPropArg id ) const
-{
-    wxPG_PROP_ARG_CALL_PROLOG_RETVAL(wxColour())
-
-    return wxColour(*((wxPGColour*)m_arrFgCols.Item(p->m_fgColIndex)));
-}
-
-void wxPropertyGrid::SetPropertyColoursToDefault( wxPGPropArg id )
-{
-    wxPG_PROP_ARG_CALL_PROLOG()
-
-    SetBackgroundColourIndex( p, 0 );
-    SetTextColourIndex( p, 0, wxPG_RECURSE );
-
-    if ( p->IsCategory() )
-    {
-        wxPropertyCategory* cat = (wxPropertyCategory*) p;
-        cat->SetTextColIndex(1);
-    }
-}
-
 // -----------------------------------------------------------------------
 // wxPropertyGrid property adding and removal
 // -----------------------------------------------------------------------
@@ -2035,7 +1778,7 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc,
 
         int rowHeight = m_fontHeight+(m_spacingy*2)+1;
         int textMarginHere = x;
-        int renderFlags = wxPGCellRenderer::Control;
+        int renderFlags = 0;
 
         int greyDepth = m_marginWidth;
         if ( !(windowStyle & wxPG_HIDE_CATEGORIES) )
@@ -2079,58 +1822,80 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc,
 
         dc.DrawLine( greyDepthX, y2-1, gridWidth-xRelMod, y2-1 );
 
-        if ( p == selected )
-        {
-            renderFlags |= wxPGCellRenderer::Selected;
-#if wxPG_REFRESH_CONTROLS_AFTER_REPAINT
-            wasSelectedPainted = true;
-#endif
-        }
-
-        wxColour rowBgCol;
+        //
+        // Need to override row colours?
         wxColour rowFgCol;
-        wxBrush rowBgBrush;
+        wxColour rowBgCol;
 
-        if ( p->IsCategory() )
-        {
-            if ( p->m_fgColIndex == 0 )
-                rowFgCol = m_colCapFore;
-            else
-                rowFgCol = *(wxPGColour*)m_arrFgCols[p->m_fgColIndex];
-            rowBgBrush = wxBrush(m_colCapBack);
-        }
-        else if ( p != selected )
+        if ( p != selected )
         {
             // Disabled may get different colour.
             if ( !p->IsEnabled() )
+            {
+                renderFlags |= wxPGCellRenderer::Disabled |
+                               wxPGCellRenderer::DontUseCellFgCol;
                 rowFgCol = m_colDisPropFore;
-            else
-                rowFgCol = *(wxPGColour*)m_arrFgCols[p->m_fgColIndex];
-
-            rowBgBrush = *(wxPGBrush*)m_arrBgBrushes[p->m_bgColIndex];
+            }
         }
         else
         {
-            // Selected gets different colour.
-            if ( reallyFocused )
-            {
-                rowFgCol = m_colSelFore;
-                rowBgBrush = wxBrush(m_colSelBack);
-            }
-            else if ( isEnabled )
-            {
-                rowFgCol = *(wxPGColour*)m_arrFgCols[p->m_fgColIndex];
-                rowBgBrush = marginBrush;
+             renderFlags |= wxPGCellRenderer::Selected;
+
+             if ( !p->IsCategory() )
+             {
+                renderFlags |= wxPGCellRenderer::DontUseCellFgCol |
+                               wxPGCellRenderer::DontUseCellBgCol;
+
+#if wxPG_REFRESH_CONTROLS_AFTER_REPAINT
+                wasSelectedPainted = true;
+#endif
+
+                // Selected gets different colour.
+                if ( reallyFocused )
+                {
+                    rowFgCol = m_colSelFore;
+                    rowBgCol = m_colSelBack;
+                }
+                else if ( isEnabled )
+                {
+                    rowFgCol = m_colPropFore;
+                    rowBgCol = m_colMargin;
+                }
+                else
+                {
+                    rowFgCol = m_colDisPropFore;
+                    rowBgCol = m_colSelBack;
+                }
             }
-            else
+        }
+
+        wxBrush rowBgBrush;
+
+        if ( rowBgCol.IsOk() )
+            rowBgBrush = wxBrush(rowBgCol);
+
+        if ( HasInternalFlag(wxPG_FL_CELL_OVERRIDES_SEL) )
+            renderFlags = renderFlags & ~wxPGCellRenderer::DontUseCellColours;
+
+        //
+        // Fill additional margin area with background colour of first cell
+        if ( greyDepthX < textMarginHere )
+        {
+            if ( !(renderFlags & wxPGCellRenderer::DontUseCellBgCol) )
             {
-                rowFgCol = m_colDisPropFore;
-                rowBgBrush = wxBrush(m_colSelBack);
+                wxPGCell& cell = p->GetCell(0);
+                rowBgCol = cell.GetBgCol();
+                rowBgBrush = wxBrush(rowBgCol);
             }
+            dc.SetBrush(rowBgBrush);
+            dc.SetPen(rowBgCol);
+            dc.DrawRectangle(greyDepthX+1, y,
+                             textMarginHere-greyDepthX, lh-1);
         }
 
         bool fontChanged = false;
 
+        // Expander button rectangle
         wxRect butRect( ((p->m_depth - 1) * m_subgroup_extramargin) - xRelMod,
                         y,
                         m_marginWidth,
@@ -2138,18 +1903,22 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc,
 
         if ( p->IsCategory() )
         {
-            // Captions are all cells merged as one
+            // Captions have their cell areas merged as one
             dc.SetFont(m_captionFont);
             fontChanged = true;
             wxRect cellRect(greyDepthX, y, gridWidth - greyDepth + 2, rowHeight-1 );
 
-            dc.SetBrush(rowBgBrush);
-            dc.SetPen(rowBgBrush.GetColour());
-            dc.SetTextForeground(rowFgCol);
+            if ( renderFlags & wxPGCellRenderer::DontUseCellBgCol )
+            {
+                dc.SetBrush(rowBgBrush);
+                dc.SetPen(rowBgCol);
+            }
 
-            dc.DrawRectangle(cellRect);
+            if ( renderFlags & wxPGCellRenderer::DontUseCellFgCol )
+            {
+                dc.SetTextForeground(rowFgCol);
+            }
 
-            // Foreground
             wxPGCellRenderer* renderer = p->GetCellRenderer(0);
             renderer->Render( dc, cellRect, this, p, 0, -1, renderFlags );
 
@@ -2176,6 +1945,11 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc,
                 cellRect.width = nextCellWidth - 1;
 
                 bool ctrlCell = false;
+                int cellRenderFlags = renderFlags;
+
+                // Tree Item Button
+                if ( ci == 0 && !HasFlag(wxPG_HIDE_MARGIN) && p->HasVisibleChildren() )
+                    DrawExpanderButton( dc, butRect, p );
 
                 // Background
                 if ( p == selected && m_wndEditor && ci == 1 )
@@ -2184,22 +1958,24 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc,
                     dc.SetBrush(editorBgCol);
                     dc.SetPen(editorBgCol);
                     dc.SetTextForeground(m_colPropFore);
+                    dc.DrawRectangle(cellRect);
 
                     if ( m_dragStatus == 0 && !(m_iFlags & wxPG_FL_CUR_USES_CUSTOM_IMAGE) )
                         ctrlCell = true;
                 }
                 else
                 {
-                    dc.SetBrush(rowBgBrush);
-                    dc.SetPen(rowBgBrush.GetColour());
-                    dc.SetTextForeground(rowFgCol);
-                }
-
-                dc.DrawRectangle(cellRect);
+                    if ( renderFlags & wxPGCellRenderer::DontUseCellBgCol )
+                    {
+                        dc.SetBrush(rowBgBrush);
+                        dc.SetPen(rowBgCol);
+                    }
 
-                // Tree Item Button
-                if ( ci == 0 && !HasFlag(wxPG_HIDE_MARGIN) && p->HasVisibleChildren() )
-                    DrawExpanderButton( dc, butRect, p );
+                    if ( renderFlags & wxPGCellRenderer::DontUseCellFgCol )
+                    {
+                        dc.SetTextForeground(rowFgCol);
+                    }
+                }
 
                 dc.SetClippingRegion(cellRect);
 
@@ -2214,19 +1990,21 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc,
                     if ( cmnVal == -1 || ci != 1 )
                     {
                         renderer = p->GetCellRenderer(ci);
-                        renderer->Render( dc, cellRect, this, p, ci, -1, renderFlags );
+                        renderer->Render( dc, cellRect, this, p, ci, -1,
+                                          cellRenderFlags );
                     }
                     else
                     {
                         renderer = GetCommonValue(cmnVal)->GetRenderer();
-                        renderer->Render( dc, cellRect, this, p, ci, -1, renderFlags );
+                        renderer->Render( dc, cellRect, this, p, ci, -1,
+                                          cellRenderFlags );
                     }
                 }
 
                 cellX += state->m_colWidths[ci];
                 if ( ci < (state->m_colWidths.size()-1) )
                     nextCellWidth = state->m_colWidths[ci+1];
-                cellRect.x = cellX; 
+                cellRect.x = cellX;
                 dc.DestroyClippingRegion(); // Is this really necessary?
                 textXAdd = 0;
             }
@@ -2393,12 +2171,7 @@ void wxPropertyGrid::Refresh( bool WXUNUSED(eraseBackground),
 
 void wxPropertyGrid::Clear()
 {
-    if ( m_selected )
-    {
-        bool selRes = DoSelectProperty(NULL, wxPG_SEL_DELETING);  // This must be before state clear
-        wxPG_CHECK_RET_DBG( selRes,
-                            wxT("failed to deselect a property (editor probably had invalid value)") );
-    }
+    ClearSelection(false);
 
     m_pState->DoClear();
 
@@ -2417,8 +2190,7 @@ void wxPropertyGrid::Clear()
 
 bool wxPropertyGrid::EnableCategories( bool enable )
 {
-    if ( !ClearSelection() )
-        return false;
+    ClearSelection(false);
 
     if ( enable )
     {
@@ -2470,13 +2242,7 @@ void wxPropertyGrid::SwitchState( wxPropertyGridPageState* pNewState )
 
     wxPGProperty* oldSelection = m_selected;
 
-    // Deselect
-    if ( m_selected )
-    {
-        bool selRes = ClearSelection();
-        wxPG_CHECK_RET_DBG( selRes,
-                            wxT("failed to deselect a property (editor probably had invalid value)") );
-    }
+    ClearSelection(false);
 
     m_pState->m_selected = oldSelection;
 
@@ -2544,9 +2310,7 @@ void wxPropertyGrid::SortChildren( wxPGPropArg id )
 
 void wxPropertyGrid::Sort()
 {
-    bool selRes = ClearSelection();  // This must be before state clear
-    wxPG_CHECK_RET_DBG( selRes,
-                        wxT("failed to deselect a property (editor probably had invalid value)") );
+    ClearSelection(false);  // This must be before state clear
 
     m_pState->Sort();
 }
@@ -2891,28 +2655,34 @@ bool wxPropertyGrid::DoOnValidationFailure( wxPGProperty* property, wxVariant& W
     if ( (vfb & wxPG_VFB_MARK_CELL) &&
          !property->HasFlag(wxPG_PROP_INVALID_VALUE) )
     {
-        wxASSERT_MSG( !property->GetCell(0) && !property->GetCell(1),
-                      wxT("Currently wxPG_VFB_MARK_CELL only works with properties with standard first two cells") );
+        unsigned int colCount = m_pState->GetColumnCount();
+
+        // We need backup marked property's cells
+        m_propCellsBackup = property->m_cells;
+
+        wxColour vfbFg = *wxWHITE;
+        wxColour vfbBg = *wxRED;
 
-        if ( !property->GetCell(0) && !property->GetCell(1) )
+        property->EnsureCells(colCount);
+
+        for ( unsigned int i=0; i<colCount; i++ )
         {
-            wxColour vfbFg = *wxWHITE;
-            wxColour vfbBg = *wxRED;
-            property->SetCell(0, new wxPGCell(property->GetLabel(), wxNullBitmap, vfbFg, vfbBg));
-            property->SetCell(1, new wxPGCell(property->GetDisplayedString(), wxNullBitmap, vfbFg, vfbBg));
+            wxPGCell& cell = property->m_cells[i];
+            cell.SetFgCol(vfbFg);
+            cell.SetBgCol(vfbBg);
+        }
 
-            DrawItemAndChildren(property);
+        DrawItemAndChildren(property);
 
-            if ( property == m_selected )
-            {
-                SetInternalFlag(wxPG_FL_CELL_OVERRIDES_SEL);
+        if ( property == m_selected )
+        {
+            SetInternalFlag(wxPG_FL_CELL_OVERRIDES_SEL);
 
-                wxWindow* editor = GetEditorControl();
-                if ( editor )
-                {
-                    editor->SetForegroundColour(vfbFg);
-                    editor->SetBackgroundColour(vfbBg);
-                }
+            wxWindow* editor = GetEditorControl();
+            if ( editor )
+            {
+                editor->SetForegroundColour(vfbFg);
+                editor->SetBackgroundColour(vfbBg);
             }
         }
     }
@@ -2938,8 +2708,8 @@ void wxPropertyGrid::DoOnValidationFailureReset( wxPGProperty* property )
 
     if ( vfb & wxPG_VFB_MARK_CELL )
     {
-        property->SetCell(0, NULL);
-        property->SetCell(1, NULL);
+        // Revert cells
+        property->m_cells = m_propCellsBackup;
 
         ClearInternalFlag(wxPG_FL_CELL_OVERRIDES_SEL);
 
@@ -3125,7 +2895,7 @@ bool wxPropertyGrid::ProcessEvent(wxEvent& event)
              (parent == m_canvas ||
               parent->GetParent() == m_canvas) )
         {
-            OnCustomEditorEvent((wxCommandEvent&)event);
+            OnCustomEditorEvent(event);
             return true;
         }
     }
@@ -3134,9 +2904,7 @@ bool wxPropertyGrid::ProcessEvent(wxEvent& event)
 
 // -----------------------------------------------------------------------
 
-// NB: It may really not be wxCommandEvent - must check if necessary
-//     (usually not).
-void wxPropertyGrid::OnCustomEditorEvent( wxCommandEvent &event )
+void wxPropertyGrid::OnCustomEditorEvent( wxEvent &event )
 {
     wxPGProperty* selected = m_selected;
 
@@ -3259,7 +3027,7 @@ void wxPropertyGrid::OnCustomEditorEvent( wxCommandEvent &event )
     else
     {
         // No value after all
-        
+
         // Regardless of editor type, unfocus editor on
         // text-editing related enter press.
         if ( event.GetEventType() == wxEVT_COMMAND_TEXT_ENTER )
@@ -3475,8 +3243,6 @@ void wxPropertyGrid::FreeEditors()
 // Call with NULL to de-select property
 bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags )
 {
-    wxPanel* canvas = GetPanel();
-
     /*
     if (p)
         wxLogDebug(wxT("SelectProperty( %s (%s[%i]) )"),p->m_label.c_str(),
@@ -3503,13 +3269,13 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags )
         wxPrintf( "Selected %s\n", m_selected->GetClassInfo()->GetClassName() );
     else
         wxPrintf( "None selected\n" );
-    
+
     if (p)
         wxPrintf( "P =  %s\n", p->GetClassInfo()->GetClassName() );
     else
         wxPrintf( "P = NULL\n" );
 */
-  
+
     // If we are frozen, then just set the values.
     if ( m_frozen )
     {
@@ -3654,7 +3420,7 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags )
 
                 if ( m_wndEditor )
                 {
-                    wxASSERT_MSG( m_wndEditor->GetParent() == canvas,
+                    wxASSERT_MSG( m_wndEditor->GetParent() == GetPanel(),
                                   wxT("CreateControls must use result of wxPropertyGrid::GetPanel() as parent of controls.") );
 
                     // Set validator, if any
@@ -3718,7 +3484,7 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags )
 
                 if ( m_wndEditor2 )
                 {
-                    wxASSERT_MSG( m_wndEditor2->GetParent() == canvas,
+                    wxASSERT_MSG( m_wndEditor2->GetParent() == GetPanel(),
                                   wxT("CreateControls must use result of wxPropertyGrid::GetPanel() as parent of controls.") );
 
                     // Get proper id for wndSecondary
@@ -3880,10 +3646,9 @@ bool wxPropertyGrid::DoCollapse( wxPGProperty* p, bool sendEvents )
     wxPGProperty* pwc = wxStaticCast(p, wxPGProperty);
 
     // If active editor was inside collapsed section, then disable it
-    if ( m_selected && m_selected->IsSomeParent (p) )
+    if ( m_selected && m_selected->IsSomeParent(p) )
     {
-        if ( !ClearSelection() )
-            return false;
+        ClearSelection(false);
     }
 
     // Store dont-center-splitter flag 'cause we need to temporarily set it
@@ -3968,8 +3733,7 @@ bool wxPropertyGrid::DoHideProperty( wxPGProperty* p, bool hide, int flags )
          ( m_selected == p || m_selected->IsSomeParent(p) )
        )
         {
-            if ( !ClearSelection() )
-                return false;
+            ClearSelection(false);
         }
 
     m_pState->DoHideProperty(p, hide, flags);
@@ -4965,19 +4729,51 @@ void wxPropertyGrid::HandleKeyEvent( wxKeyEvent &event, bool fromChild )
 
     if ( keycode == WXK_TAB )
     {
+        wxWindow* mainControl;
+
+        if ( HasInternalFlag(wxPG_FL_IN_MANAGER) )
+            mainControl = GetParent();
+        else
+            mainControl = this;
+
         if ( !event.ShiftDown() )
         {
             if ( !editorFocused && m_wndEditor )
+            {
                 DoSelectProperty( m_selected, wxPG_SEL_FOCUS );
+            }
             else
+            {
+                // Tab traversal workaround for platforms on which
+                // wxWindow::Navigate() may navigate into first child
+                // instead of next sibling. Does not work perfectly
+                // in every scenario (for instance, when property grid
+                // is either first or last control).
+            #if defined(__WXGTK__)
+                wxWindow* sibling = mainControl->GetNextSibling();
+                if ( sibling )
+                    sibling->SetFocusFromKbd();
+            #else
                 Navigate(wxNavigationKeyEvent::IsForward);
+            #endif
+            }
         }
         else
         {
             if ( editorFocused )
+            {
                 UnfocusEditor();
+            }
             else
+            {
+            #if defined(__WXGTK__)
+                wxWindow* sibling = mainControl->GetPrevSibling();
+                if ( sibling )
+                    sibling->SetFocusFromKbd();
+            #else
                 Navigate(wxNavigationKeyEvent::IsBackward);
+            #endif
+            }
         }
 
         return;
@@ -5403,12 +5199,6 @@ wxPGChoiceEntry::wxPGChoiceEntry()
 {
 }
 
-wxPGChoiceEntry::wxPGChoiceEntry( const wxPGChoiceEntry& entry )
-    : wxPGCell( entry.GetText(), entry.GetBitmap(),
-        entry.GetFgCol(), entry.GetBgCol() ), m_value(entry.GetValue())
-{
-}
-
 // -----------------------------------------------------------------------
 // wxPGChoicesData
 // -----------------------------------------------------------------------
@@ -5425,13 +5215,6 @@ wxPGChoicesData::~wxPGChoicesData()
 
 void wxPGChoicesData::Clear()
 {
-    unsigned int i;
-
-    for ( i=0; i<m_items.size(); i++ )
-    {
-        delete Item(i);
-    }
-
     m_items.clear();
 }
 
@@ -5439,10 +5222,32 @@ void wxPGChoicesData::CopyDataFrom( wxPGChoicesData* data )
 {
     wxASSERT( m_items.size() == 0 );
 
-    unsigned int i;
+    m_items = data->m_items;
+}
 
-    for ( i=0; i<data->GetCount(); i++ )
-        m_items.push_back( new wxPGChoiceEntry(*data->Item(i)) );
+wxPGChoiceEntry& wxPGChoicesData::Insert( int index,
+                                          const wxPGChoiceEntry& item )
+{
+    wxVector<wxPGChoiceEntry>::iterator it;
+    if ( index == -1 )
+    {
+        it = m_items.end();
+        index = (int) m_items.size();
+    }
+    else
+    {
+        it = m_items.begin() + index;
+    }
+
+    m_items.insert(it, item);
+
+    wxPGChoiceEntry& ownEntry = m_items[index];
+
+    // Need to fix value?
+    if ( ownEntry.GetValue() == wxPG_INVALID_VALUE )
+        ownEntry.SetValue(index);
+
+    return ownEntry;
 }
 
 // -----------------------------------------------------------------------
@@ -5453,9 +5258,8 @@ wxPGChoiceEntry& wxPGChoices::Add( const wxString& label, int value )
 {
     EnsureData();
 
-    wxPGChoiceEntry* p = new wxPGChoiceEntry(label, value);
-    m_data->Insert( -1, p );
-    return *p;
+    wxPGChoiceEntry entry(label, value);
+    return m_data->Insert( -1, entry );
 }
 
 // -----------------------------------------------------------------------
@@ -5464,10 +5268,9 @@ wxPGChoiceEntry& wxPGChoices::Add( const wxString& label, const wxBitmap& bitmap
 {
     EnsureData();
 
-    wxPGChoiceEntry* p = new wxPGChoiceEntry(label, value);
-    p->SetBitmap(bitmap);
-    m_data->Insert( -1, p );
-    return *p;
+    wxPGChoiceEntry entry(label, value);
+    entry.SetBitmap(bitmap);
+    return m_data->Insert( -1, entry );
 }
 
 // -----------------------------------------------------------------------
@@ -5475,10 +5278,7 @@ wxPGChoiceEntry& wxPGChoices::Add( const wxString& label, const wxBitmap& bitmap
 wxPGChoiceEntry& wxPGChoices::Insert( const wxPGChoiceEntry& entry, int index )
 {
     EnsureData();
-
-    wxPGChoiceEntry* p = new wxPGChoiceEntry(entry);
-    m_data->Insert(index, p);
-    return *p;
+    return m_data->Insert( index, entry );
 }
 
 // -----------------------------------------------------------------------
@@ -5487,9 +5287,8 @@ wxPGChoiceEntry& wxPGChoices::Insert( const wxString& label, int index, int valu
 {
     EnsureData();
 
-    wxPGChoiceEntry* p = new wxPGChoiceEntry(label, value);
-    m_data->Insert( index, p );
-    return *p;
+    wxPGChoiceEntry entry(label, value);
+    return m_data->Insert( index, entry );
 }
 
 // -----------------------------------------------------------------------
@@ -5508,9 +5307,8 @@ wxPGChoiceEntry& wxPGChoices::AddAsSorted( const wxString& label, int value )
         index++;
     }
 
-    wxPGChoiceEntry* p = new wxPGChoiceEntry(label, value);
-    m_data->Insert( index, p );
-    return *p;
+    wxPGChoiceEntry entry(label, value);
+    return m_data->Insert( index, entry );
 }
 
 // -----------------------------------------------------------------------
@@ -5526,28 +5324,11 @@ void wxPGChoices::Add( const wxChar** labels, const ValArrItem* values )
     unsigned int i;
     for ( i = 0; i < itemcount; i++ )
     {
-        int value = wxPG_INVALID_VALUE;
+        int value = i;
         if ( values )
             value = values[i];
-        m_data->Insert( -1, new wxPGChoiceEntry(labels[i], value) );
-    }
-}
-
-// -----------------------------------------------------------------------
-
-void wxPGChoices::Add( const wxArrayString& arr, const ValArrItem* values )
-{
-    EnsureData();
-
-    unsigned int i;
-    unsigned int itemcount = arr.size();
-
-    for ( i = 0; i < itemcount; i++ )
-    {
-        int value = wxPG_INVALID_VALUE;
-        if ( values )
-            value = values[i];
-        m_data->Insert( -1, new wxPGChoiceEntry(arr[i], value) );
+        wxPGChoiceEntry entry(labels[i], value);
+        m_data->Insert( i, entry );
     }
 }
 
@@ -5562,10 +5343,11 @@ void wxPGChoices::Add( const wxArrayString& arr, const wxArrayInt& arrint )
 
     for ( i = 0; i < itemcount; i++ )
     {
-        int value = wxPG_INVALID_VALUE;
+        int value = i;
         if ( &arrint && arrint.size() )
             value = arrint[i];
-        m_data->Insert( -1, new wxPGChoiceEntry(arr[i], value) );
+        wxPGChoiceEntry entry(arr[i], value);
+        m_data->Insert( i, entry );
     }
 }
 
@@ -5574,9 +5356,6 @@ void wxPGChoices::Add( const wxArrayString& arr, const wxArrayInt& arrint )
 void wxPGChoices::RemoveAt(size_t nIndex, size_t count)
 {
     wxASSERT( m_data->m_refCount != 0xFFFFFFF );
-    unsigned int i;
-    for ( i=nIndex; i<(nIndex+count); i++)
-        delete m_data->Item(i);
     m_data->m_items.erase(m_data->m_items.begin()+nIndex,
                           m_data->m_items.begin()+nIndex+count);
 }
@@ -5590,7 +5369,8 @@ int wxPGChoices::Index( const wxString& str ) const
         unsigned int i;
         for ( i=0; i< m_data->GetCount(); i++ )
         {
-            if ( m_data->Item(i)->GetText() == str )
+            const wxPGChoiceEntry& entry = m_data->Item(i);
+            if ( entry.HasText() && entry.GetText() == str )
                 return i;
         }
     }
@@ -5606,7 +5386,8 @@ int wxPGChoices::Index( int val ) const
         unsigned int i;
         for ( i=0; i< m_data->GetCount(); i++ )
         {
-            if ( m_data->Item(i)->GetValue() == val )
+            const wxPGChoiceEntry& entry = m_data->Item(i);
+            if ( entry.GetValue() == val )
                 return i;
         }
     }
@@ -5629,13 +5410,6 @@ wxArrayString wxPGChoices::GetLabels() const
 
 // -----------------------------------------------------------------------
 
-bool wxPGChoices::HasValues() const
-{
-    return true;
-}
-
-// -----------------------------------------------------------------------
-
 wxArrayInt wxPGChoices::GetValuesForStrings( const wxArrayString& strings ) const
 {
     wxArrayInt arr;
@@ -5658,7 +5432,7 @@ wxArrayInt wxPGChoices::GetValuesForStrings( const wxArrayString& strings ) cons
 
 // -----------------------------------------------------------------------
 
-wxArrayInt wxPGChoices::GetIndicesForStrings( const wxArrayString& strings, 
+wxArrayInt wxPGChoices::GetIndicesForStrings( const wxArrayString& strings,
                                               wxArrayString* unmatched ) const
 {
     wxArrayInt arr;
@@ -5857,7 +5631,8 @@ wxPGProperty* wxPropertyGridPopulator::Add( const wxString& propClass,
     m_state->DoInsert(parent, -1, property);
 
     if ( propValue )
-        property->SetValueFromString( *propValue, wxPG_FULL_VALUE );
+        property->SetValueFromString( *propValue, wxPG_FULL_VALUE|
+                                                  wxPG_PROGRAMMATIC_VALUE );
 
     return property;
 }