]> git.saurik.com Git - wxWidgets.git/blobdiff - src/propgrid/manager.cpp
first stab at supporting custom renderers
[wxWidgets.git] / src / propgrid / manager.cpp
index d844503d3899f916ab129246cf0208b41646e91f..2030ec2ea303ff10a725113a9fa02be426285e05 100644 (file)
@@ -6,7 +6,7 @@
 // Created:     2005-01-14
 // RCS-ID:      $Id$
 // Copyright:   (c) Jaakko Salli
 // Created:     2005-01-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".
@@ -76,7 +76,7 @@ const char wxPropertyGridManagerNameStr[] = "wxPropertyGridManager";
 
 
 // Categoric Mode Icon
 
 
 // Categoric Mode Icon
-static const char* gs_xpm_catmode[] = {
+static const char* const gs_xpm_catmode[] = {
 "16 16 5 1",
 ". c none",
 "B c black",
 "16 16 5 1",
 ". c none",
 "B c black",
@@ -102,7 +102,7 @@ static const char* gs_xpm_catmode[] = {
 };
 
 // Alphabetic Mode Icon
 };
 
 // Alphabetic Mode Icon
-static const char* gs_xpm_noncatmode[] = {
+static const char* const gs_xpm_noncatmode[] = {
 "16 16 5 1",
 ". c none",
 "B c black",
 "16 16 5 1",
 ". c none",
 "B c black",
@@ -128,7 +128,7 @@ static const char* gs_xpm_noncatmode[] = {
 };
 
 // Default Page Icon.
 };
 
 // Default Page Icon.
-static const char* gs_xpm_defpage[] = {
+static const char* const gs_xpm_defpage[] = {
 "16 16 5 1",
 ". c none",
 "B c black",
 "16 16 5 1",
 ". c none",
 "B c black",
@@ -209,18 +209,197 @@ void wxPropertyGridPage::SetSplitterPosition( int splitterPos, int col )
 
 void wxPropertyGridPage::DoSetSplitterPosition( int pos,
                                                 int splitterColumn,
 
 void wxPropertyGridPage::DoSetSplitterPosition( int pos,
                                                 int splitterColumn,
-                                                bool allPages,
-                                                bool fromAutoCenter )
+                                                int flags )
 {
 {
-    if ( allPages && m_manager->GetPageCount() )
+    if ( (flags & wxPG_SPLITTER_ALL_PAGES) && m_manager->GetPageCount() )
         m_manager->SetSplitterPosition( pos, splitterColumn );
     else
         wxPropertyGridPageState::DoSetSplitterPosition( pos,
                                                         splitterColumn,
         m_manager->SetSplitterPosition( pos, splitterColumn );
     else
         wxPropertyGridPageState::DoSetSplitterPosition( pos,
                                                         splitterColumn,
-                                                        allPages,
-                                                        fromAutoCenter );
+                                                        flags );
 }
 
 }
 
+// -----------------------------------------------------------------------
+// wxPGHeaderCtrl
+// -----------------------------------------------------------------------
+
+#if wxUSE_HEADERCTRL
+
+class wxPGHeaderCtrl : public wxHeaderCtrl
+{
+public:
+    wxPGHeaderCtrl(wxPropertyGridManager* manager) :
+        wxHeaderCtrl()
+    {
+        m_manager = manager;
+        EnsureColumnCount(2);
+
+        // Seed titles with defaults
+        m_columns[0]->SetTitle(_("Property"));
+        m_columns[1]->SetTitle(_("Value"));
+    }
+
+    virtual ~wxPGHeaderCtrl()
+    {
+        for (unsigned int i=0; i<m_columns.size(); i++ )
+            delete m_columns[i];
+    }
+
+    int DetermineColumnWidth(unsigned int idx, int* pMinWidth) const
+    {
+        const wxPropertyGridPage* page = m_page;
+        int colWidth = page->GetColumnWidth(idx);
+        int colMinWidth = page->GetColumnMinWidth(idx);
+        if ( idx == 0 )
+        {
+            wxPropertyGrid* pg = m_manager->GetGrid();
+            int margin = pg->GetMarginWidth();
+
+            // Compensate for the internal border
+            margin += (pg->GetSize().x - pg->GetClientSize().x) / 2;
+
+            colWidth += margin;
+            colMinWidth += margin;
+        }
+        *pMinWidth = colMinWidth;
+        return colWidth;
+    }
+
+    void OnPageChanged(const wxPropertyGridPage* page)
+    {
+        m_page = page;
+        OnPageUpdated();
+    }
+
+    void OnPageUpdated()
+    {
+        // Get column info from the page
+        const wxPropertyGridPage* page = m_page;
+        unsigned int colCount = page->GetColumnCount();
+        EnsureColumnCount(colCount);
+
+        for ( unsigned int i=0; i<colCount; i++ )
+        {
+            wxHeaderColumnSimple* colInfo = m_columns[i];
+            int colMinWidth = 0;
+            int colWidth = DetermineColumnWidth(i, &colMinWidth);
+            colInfo->SetWidth(colWidth);
+            colInfo->SetMinWidth(colMinWidth);
+        }
+
+        SetColumnCount(colCount);
+    }
+
+    void OnColumWidthsChanged()
+    {
+        const wxPropertyGridPage* page = m_page;
+        unsigned int colCount = page->GetColumnCount();
+
+        for ( unsigned int i=0; i<colCount; i++ )
+        {
+            wxHeaderColumnSimple* colInfo = m_columns[i];
+            int colMinWidth = 0;
+            int colWidth = DetermineColumnWidth(i, &colMinWidth);
+            colInfo->SetWidth(colWidth);
+            colInfo->SetMinWidth(colMinWidth);
+            UpdateColumn(i);
+        }
+    }
+
+    virtual const wxHeaderColumn& GetColumn(unsigned int idx) const
+    {
+        return *m_columns[idx];
+    }
+
+    void SetColumnTitle(unsigned int idx, const wxString& title)
+    {
+        EnsureColumnCount(idx+1);
+        m_columns[idx]->SetTitle(title);
+    }
+
+private:
+    void EnsureColumnCount(unsigned int count)
+    {
+        while ( m_columns.size() < count )
+        {
+            wxHeaderColumnSimple* colInfo = new wxHeaderColumnSimple("");
+            m_columns.push_back(colInfo);
+        }
+    }
+
+    void OnSetColumnWidth(int col, int colWidth)
+    {
+        wxPropertyGrid* pg = m_manager->GetGrid();
+
+        // Compensate for the internal border
+        int x = -((pg->GetSize().x - pg->GetClientSize().x) / 2);
+
+        for ( int i=0; i<col; i++ )
+            x += m_columns[i]->GetWidth();
+
+        x += colWidth;
+
+        pg->DoSetSplitterPosition(x, col,
+                                  wxPG_SPLITTER_REFRESH |
+                                  wxPG_SPLITTER_FROM_EVENT);
+    }
+
+    virtual bool ProcessEvent( wxEvent& event )
+    {
+        if ( event.IsKindOf(CLASSINFO(wxHeaderCtrlEvent)) )
+        {
+            wxHeaderCtrlEvent& hcEvent =
+                static_cast<wxHeaderCtrlEvent&>(event);
+
+            wxPropertyGrid* pg = m_manager->GetGrid();
+            int col = hcEvent.GetColumn();
+            int evtType = event.GetEventType();
+
+            if ( evtType == wxEVT_COMMAND_HEADER_RESIZING )
+            {
+                int colWidth = hcEvent.GetWidth();
+
+                OnSetColumnWidth(col, colWidth);
+
+                pg->SendEvent(wxEVT_PG_COL_DRAGGING,
+                              NULL, NULL, 0,
+                              (unsigned int)col);
+
+                return true;
+            }
+            else if ( evtType == wxEVT_COMMAND_HEADER_BEGIN_RESIZE )
+            {
+                // Never allow column resize if layout is static
+                if ( m_manager->HasFlag(wxPG_STATIC_SPLITTER) )
+                    hcEvent.Veto();
+                // Allow application to veto dragging
+                else if ( pg->SendEvent(wxEVT_PG_COL_BEGIN_DRAG,
+                                        NULL, NULL, 0,
+                                        (unsigned int)col) )
+                    hcEvent.Veto();
+
+                return true;
+            }
+            else if ( evtType == wxEVT_COMMAND_HEADER_END_RESIZE )
+            {
+                pg->SendEvent(wxEVT_PG_COL_END_DRAG,
+                              NULL, NULL, 0,
+                              (unsigned int)col);
+
+                return true;
+            }
+        }
+
+        return wxHeaderCtrl::ProcessEvent(event);
+    }
+
+    wxPropertyGridManager*          m_manager;
+    const wxPropertyGridPage*       m_page;
+    wxVector<wxHeaderColumnSimple*> m_columns;
+};
+
+#endif // wxUSE_HEADERCTRL
+
 // -----------------------------------------------------------------------
 // wxPropertyGridManager
 // -----------------------------------------------------------------------
 // -----------------------------------------------------------------------
 // wxPropertyGridManager
 // -----------------------------------------------------------------------
@@ -232,12 +411,6 @@ void wxPropertyGridPage::DoSetSplitterPosition( int pos,
 
 IMPLEMENT_CLASS(wxPropertyGridManager, wxPanel)
 
 
 IMPLEMENT_CLASS(wxPropertyGridManager, wxPanel)
 
-#define ID_ADVTOOLBAR_OFFSET        1
-#define ID_ADVHELPCAPTION_OFFSET    2
-#define ID_ADVHELPCONTENT_OFFSET    3
-//#define ID_ADVBUTTON_OFFSET         4
-#define ID_ADVTBITEMSBASE_OFFSET    5   // Must be last.
-
 // -----------------------------------------------------------------------
 
 BEGIN_EVENT_TABLE(wxPropertyGridManager, wxPanel)
 // -----------------------------------------------------------------------
 
 BEGIN_EVENT_TABLE(wxPropertyGridManager, wxPanel)
@@ -289,6 +462,11 @@ bool wxPropertyGridManager::Create( wxWindow *parent,
                                 name );
     Init2(style);
 
                                 name );
     Init2(style);
 
+    // FIXME: this changes call ordering so wxPropertyGrid is created
+    // immediately, before SetExtraStyle has a chance to be called. However,
+    // without it, we may get assertions if size is wxDefaultSize.
+    //SetInitialSize(size);
+
     return res;
 }
 
     return res;
 }
 
@@ -304,6 +482,10 @@ void wxPropertyGridManager::Init1()
 
 #if wxUSE_TOOLBAR
     m_pToolbar = NULL;
 
 #if wxUSE_TOOLBAR
     m_pToolbar = NULL;
+#endif
+#if wxUSE_HEADERCTRL
+    m_pHeaderCtrl = NULL;
+    m_showHeader = false;
 #endif
     m_pTxtHelpCaption = NULL;
     m_pTxtHelpContent = NULL;
 #endif
     m_pTxtHelpCaption = NULL;
     m_pTxtHelpContent = NULL;
@@ -320,6 +502,9 @@ void wxPropertyGridManager::Init1()
 
     m_nextDescBoxSize = -1;
 
 
     m_nextDescBoxSize = -1;
 
+    m_categorizedModeToolId = -1;
+    m_alphabeticModeToolId = -1;
+
     m_extraHeight = 0;
     m_dragStatus = 0;
     m_onSplitter = 0;
     m_extraHeight = 0;
     m_dragStatus = 0;
     m_onSplitter = 0;
@@ -329,15 +514,9 @@ void wxPropertyGridManager::Init1()
 // -----------------------------------------------------------------------
 
 // These flags are always used in wxPropertyGrid integrated in wxPropertyGridManager.
 // -----------------------------------------------------------------------
 
 // These flags are always used in wxPropertyGrid integrated in wxPropertyGridManager.
-#ifndef __WXMAC__
-  #define wxPG_MAN_PROPGRID_FORCED_FLAGS (wxSIMPLE_BORDER| \
+#define wxPG_MAN_PROPGRID_FORCED_FLAGS (  wxBORDER_THEME | \
                                           wxNO_FULL_REPAINT_ON_RESIZE| \
                                           wxCLIP_CHILDREN)
                                           wxNO_FULL_REPAINT_ON_RESIZE| \
                                           wxCLIP_CHILDREN)
-#else
-  #define wxPG_MAN_PROPGRID_FORCED_FLAGS (wxNO_BORDER| \
-                                          wxNO_FULL_REPAINT_ON_RESIZE| \
-                                          wxCLIP_CHILDREN)
-#endif
 
 // Which flags can be passed to underlying wxPropertyGrid.
 #define wxPG_MAN_PASS_FLAGS_MASK       (0xFFF0|wxTAB_TRAVERSAL)
 
 // Which flags can be passed to underlying wxPropertyGrid.
 #define wxPG_MAN_PASS_FLAGS_MASK       (0xFFF0|wxTAB_TRAVERSAL)
@@ -373,17 +552,28 @@ void wxPropertyGridManager::Init2( int style )
     if ( baseId < 0 )
         baseId = wxPG_MAN_ALTERNATE_BASE_ID;
 
     if ( baseId < 0 )
         baseId = wxPG_MAN_ALTERNATE_BASE_ID;
 
-    m_baseId = baseId;
-
 #ifdef __WXMAC__
    // Smaller controls on Mac
    SetWindowVariant(wxWINDOW_VARIANT_SMALL);
 #endif
 
 #ifdef __WXMAC__
    // Smaller controls on Mac
    SetWindowVariant(wxWINDOW_VARIANT_SMALL);
 #endif
 
+   long propGridFlags = (m_windowStyle&wxPG_MAN_PASS_FLAGS_MASK)
+                        |wxPG_MAN_PROPGRID_FORCED_FLAGS;
+
+   propGridFlags &= ~wxBORDER_MASK;
+
+   if ((style & wxPG_NO_INTERNAL_BORDER) == 0)
+   {
+       propGridFlags |= wxBORDER_THEME;
+   }
+   else
+   {
+       propGridFlags |= wxBORDER_NONE;
+       wxWindow::SetExtraStyle(wxPG_EX_TOOLBAR_SEPARATOR);
+   }
+
     // Create propertygrid.
     // Create propertygrid.
-    m_pPropGrid->Create(this,baseId,wxPoint(0,0),csz,
-                        (m_windowStyle&wxPG_MAN_PASS_FLAGS_MASK)
-                            |wxPG_MAN_PROPGRID_FORCED_FLAGS);
+    m_pPropGrid->Create(this,baseId,wxPoint(0,0),csz, propGridFlags);
 
     m_pPropGrid->m_eventObject = this;
 
 
     m_pPropGrid->m_eventObject = this;
 
@@ -395,20 +585,16 @@ void wxPropertyGridManager::Init2( int style )
 
     m_pPropGrid->SetExtraStyle(wxPG_EX_INIT_NOCAT);
 
 
     m_pPropGrid->SetExtraStyle(wxPG_EX_INIT_NOCAT);
 
-    m_nextTbInd = baseId+ID_ADVTBITEMSBASE_OFFSET + 2;
-
-
     // Connect to property grid onselect event.
     // NB: Even if wxID_ANY is used, this doesn't connect properly in wxPython
     //     (see wxPropertyGridManager::ProcessEvent).
     // Connect to property grid onselect event.
     // NB: Even if wxID_ANY is used, this doesn't connect properly in wxPython
     //     (see wxPropertyGridManager::ProcessEvent).
-    Connect(m_pPropGrid->GetId()/*wxID_ANY*/,
-            wxEVT_PG_SELECTED,
-            wxPropertyGridEventHandler(wxPropertyGridManager::OnPropertyGridSelect) );
+    Connect(m_pPropGrid->GetId(),
+     wxEVT_PG_SELECTED,
+     wxPropertyGridEventHandler(wxPropertyGridManager::OnPropertyGridSelect));
 
 
-    // Connect to toolbar button events.
-    Connect(baseId+ID_ADVTBITEMSBASE_OFFSET,baseId+ID_ADVTBITEMSBASE_OFFSET+50,
-            wxEVT_COMMAND_TOOL_CLICKED,
-            wxCommandEventHandler(wxPropertyGridManager::OnToolbarClick) );
+    Connect(m_pPropGrid->GetId(),
+            wxEVT_PG_COL_DRAGGING,
+            wxPropertyGridEventHandler(wxPropertyGridManager::OnPGColDrag));
 
     // Optional initial controls.
     m_width = -12345;
 
     // Optional initial controls.
     m_width = -12345;
@@ -423,8 +609,8 @@ wxPropertyGridManager::~wxPropertyGridManager()
 {
     END_MOUSE_CAPTURE
 
 {
     END_MOUSE_CAPTURE
 
-    m_pPropGrid->DoSelectProperty(NULL);
-    m_pPropGrid->m_pState = NULL;
+    //m_pPropGrid->ClearSelection();
+    wxDELETE(m_pPropGrid);
 
     size_t i;
     for ( i=0; i<m_arrPages.size(); i++ )
 
     size_t i;
     for ( i=0; i<m_arrPages.size(); i++ )
@@ -528,6 +714,18 @@ void wxPropertyGridManager::SetWindowStyleFlag( long style )
 
 // -----------------------------------------------------------------------
 
 
 // -----------------------------------------------------------------------
 
+bool wxPropertyGridManager::Reparent( wxWindowBase *newParent )
+{
+    if ( m_pPropGrid )
+        m_pPropGrid->OnTLPChanging((wxWindow*)newParent);
+
+    bool res = wxPanel::Reparent(newParent);
+
+    return res;
+}
+
+// -----------------------------------------------------------------------
+
 // Actually shows given page.
 bool wxPropertyGridManager::DoSelectPage( int index )
 {
 // Actually shows given page.
 bool wxPropertyGridManager::DoSelectPage( int index )
 {
@@ -541,7 +739,7 @@ bool wxPropertyGridManager::DoSelectPage( int index )
     if ( m_selPage == index )
         return true;
 
     if ( m_selPage == index )
         return true;
 
-    if ( m_pPropGrid->m_selected )
+    if ( m_pPropGrid->GetSelection() )
     {
         if ( !m_pPropGrid->ClearSelection() )
             return false;
     {
         if ( !m_pPropGrid->ClearSelection() )
             return false;
@@ -585,12 +783,17 @@ bool wxPropertyGridManager::DoSelectPage( int index )
     if ( m_pToolbar )
     {
         if ( index >= 0 )
     if ( m_pToolbar )
     {
         if ( index >= 0 )
-            m_pToolbar->ToggleTool( nextPage->m_id, true );
+            m_pToolbar->ToggleTool( nextPage->m_toolId, true );
         else
         else
-            m_pToolbar->ToggleTool( prevPage->m_id, false );
+            m_pToolbar->ToggleTool( prevPage->m_toolId, false );
     }
 #endif
 
     }
 #endif
 
+#if wxUSE_HEADERCTRL
+    if ( m_showHeader )
+        m_pHeaderCtrl->OnPageChanged(nextPage);
+#endif
+
     return true;
 }
 
     return true;
 }
 
@@ -657,15 +860,14 @@ wxPropertyGridPageState* wxPropertyGridManager::GetPageState( int page ) const
 
 void wxPropertyGridManager::Clear()
 {
 
 void wxPropertyGridManager::Clear()
 {
+    m_pPropGrid->ClearSelection(false);
+
     m_pPropGrid->Freeze();
 
     int i;
     for ( i=(int)GetPageCount()-1; i>=0; i-- )
         RemovePage(i);
 
     m_pPropGrid->Freeze();
 
     int i;
     for ( i=(int)GetPageCount()-1; i>=0; i-- )
         RemovePage(i);
 
-    // Reset toolbar ids
-    m_nextTbInd = m_baseId+ID_ADVTBITEMSBASE_OFFSET + 2;
-
     m_pPropGrid->Thaw();
 }
 
     m_pPropGrid->Thaw();
 }
 
@@ -706,15 +908,20 @@ void wxPropertyGridManager::SetColumnCount( int colCount, int page )
 
     GetPageState(page)->SetColumnCount( colCount );
     GetGrid()->Refresh();
 
     GetPageState(page)->SetColumnCount( colCount );
     GetGrid()->Refresh();
+
+#if wxUSE_HEADERCTRL
+    if ( m_showHeader )
+        m_pHeaderCtrl->OnPageUpdated();
+#endif
 }
 // -----------------------------------------------------------------------
 
 size_t wxPropertyGridManager::GetPageCount() const
 {
 }
 // -----------------------------------------------------------------------
 
 size_t wxPropertyGridManager::GetPageCount() const
 {
-       if ( !(m_iFlags & wxPG_MAN_FL_PAGE_INSERTED) )
-               return 0;
+    if ( !(m_iFlags & wxPG_MAN_FL_PAGE_INSERTED) )
+        return 0;
 
 
-       return m_arrPages.size();
+    return m_arrPages.size();
 }
 
 // -----------------------------------------------------------------------
 }
 
 // -----------------------------------------------------------------------
@@ -779,14 +986,17 @@ wxPropertyGridPage* wxPropertyGridManager::InsertPage( int index,
         state->InitNonCatMode();
     }
 
         state->InitNonCatMode();
     }
 
-    if ( label.length() )
+    if ( !label.empty() )
     {
         wxASSERT_MSG( !pageObj->m_label.length(),
                       wxT("If page label is given in constructor, empty label must be given in AddPage"));
         pageObj->m_label = label;
     }
 
     {
         wxASSERT_MSG( !pageObj->m_label.length(),
                       wxT("If page label is given in constructor, empty label must be given in AddPage"));
         pageObj->m_label = label;
     }
 
-    pageObj->m_id = m_nextTbInd;
+    pageObj->m_toolId = -1;
+
+    if ( !HasFlag(wxPG_SPLITTER_AUTO_CENTER) )
+        pageObj->m_dontCenterSplitter = true;
 
     if ( isPageInserted )
         m_arrPages.push_back( pageObj );
 
     if ( isPageInserted )
         m_arrPages.push_back( pageObj );
@@ -806,14 +1016,23 @@ wxPropertyGridPage* wxPropertyGridManager::InsertPage( int index,
                  m_pToolbar->GetToolsCount() < 3 )
                 m_pToolbar->AddSeparator();
 
                  m_pToolbar->GetToolsCount() < 3 )
                 m_pToolbar->AddSeparator();
 
+            wxToolBarToolBase* tool;
+
             if ( &bmp != &wxNullBitmap )
             if ( &bmp != &wxNullBitmap )
-                m_pToolbar->AddTool(m_nextTbInd,label,bmp,label,wxITEM_RADIO);
-                //m_pToolbar->InsertTool(index+3,m_nextTbInd,bmp);
+                tool = m_pToolbar->AddTool(wxID_ANY, label, bmp,
+                                           label, wxITEM_RADIO);
             else
             else
-                m_pToolbar->AddTool(m_nextTbInd,label,wxBitmap( (const char**)gs_xpm_defpage ),
-                    label,wxITEM_RADIO);
+                tool = m_pToolbar->AddTool(wxID_ANY, label,
+                                           wxBitmap(gs_xpm_defpage),
+                                           label, wxITEM_RADIO);
+
+            pageObj->m_toolId = tool->GetId();
 
 
-            m_nextTbInd++;
+            // Connect to toolbar button events.
+            Connect(pageObj->m_toolId,
+                    wxEVT_COMMAND_TOOL_CLICKED,
+                    wxCommandEventHandler(
+                        wxPropertyGridManager::OnToolbarClick));
 
             m_pToolbar->Realize();
         }
 
             m_pToolbar->Realize();
         }
@@ -869,6 +1088,44 @@ bool wxPropertyGridManager::IsPageModified( size_t index ) const
 
 // -----------------------------------------------------------------------
 
 
 // -----------------------------------------------------------------------
 
+#if wxUSE_HEADERCTRL
+void wxPropertyGridManager::ShowHeader(bool show)
+{
+    if ( show != m_showHeader)
+    {
+        m_showHeader = show;
+        RecreateControls();
+    }
+}
+#endif
+
+// -----------------------------------------------------------------------
+
+#if wxUSE_HEADERCTRL
+void wxPropertyGridManager::SetColumnTitle( int idx, const wxString& title )
+{
+    if ( !m_pHeaderCtrl )
+        ShowHeader();
+
+    m_pHeaderCtrl->SetColumnTitle(idx, title);
+}
+#endif
+
+// -----------------------------------------------------------------------
+
+bool wxPropertyGridManager::IsPropertySelected( wxPGPropArg id ) const
+{
+    wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
+    for ( unsigned int i=0; i<GetPageCount(); i++ )
+    {
+        if ( GetPageState(i)->DoIsPropertySelected(p) )
+            return true;
+    }
+    return false;
+}
+
+// -----------------------------------------------------------------------
+
 wxPGProperty* wxPropertyGridManager::GetPageRoot( int index ) const
 {
     wxASSERT( index >= 0 );
 wxPGProperty* wxPropertyGridManager::GetPageRoot( int index ) const
 {
     wxASSERT( index >= 0 );
@@ -1061,6 +1318,18 @@ void wxPropertyGridManager::RecalculatePositions( int width, int height )
     {
         m_pToolbar->SetSize(0, 0, width, -1);
         propgridY += m_pToolbar->GetSize().y;
     {
         m_pToolbar->SetSize(0, 0, width, -1);
         propgridY += m_pToolbar->GetSize().y;
+
+        if (GetExtraStyle() & wxPG_EX_TOOLBAR_SEPARATOR)
+            propgridY += 1;
+    }
+#endif
+
+    // Header comes after the tool bar
+#if wxUSE_HEADERCTRL
+    if ( m_showHeader )
+    {
+        m_pHeaderCtrl->SetSize(0, propgridY, width, -1);
+        propgridY += m_pHeaderCtrl->GetSize().y;
     }
 #endif
 
     }
 #endif
 
@@ -1141,8 +1410,20 @@ void wxPropertyGridManager::OnPaint( wxPaintEvent& WXUNUSED(event) )
     // Update everything inside the box
     wxRect r = GetUpdateRegion().GetBox();
 
     // Update everything inside the box
     wxRect r = GetUpdateRegion().GetBox();
 
+    if (GetExtraStyle() & wxPG_EX_TOOLBAR_SEPARATOR)
+    {
+        if (m_pToolbar && m_pPropGrid)
+        {
+            wxPen marginPen(m_pPropGrid->GetMarginColour());
+            dc.SetPen(marginPen);
+
+            int y = m_pPropGrid->GetPosition().y-1;
+            dc.DrawLine(0, y, GetClientSize().x, y);
+        }
+    }
+
     // Repaint splitter and any other description box decorations
     // Repaint splitter and any other description box decorations
-    if ( (r.y + r.height) >= m_splitterY )
+    if ( (r.y + r.height) >= m_splitterY && m_splitterY != -1)
         RepaintDescBoxDecorations( dc, m_splitterY, m_width, m_height );
 }
 
         RepaintDescBoxDecorations( dc, m_splitterY, m_width, m_height );
 }
 
@@ -1173,20 +1454,20 @@ void wxPropertyGridManager::RecreateControls()
     if ( was_shown )
         Show ( false );
 
     if ( was_shown )
         Show ( false );
 
-    wxWindowID baseId = m_pPropGrid->GetId();
-    if ( baseId < 0 )
-        baseId = wxPG_MAN_ALTERNATE_BASE_ID;
-
 #if wxUSE_TOOLBAR
     if ( m_windowStyle & wxPG_TOOLBAR )
     {
         // Has toolbar.
         if ( !m_pToolbar )
         {
 #if wxUSE_TOOLBAR
     if ( m_windowStyle & wxPG_TOOLBAR )
     {
         // Has toolbar.
         if ( !m_pToolbar )
         {
-            m_pToolbar = new wxToolBar(this,baseId+ID_ADVTOOLBAR_OFFSET,
-                                       wxDefaultPosition,wxDefaultSize,
-                                       ((GetExtraStyle()&wxPG_EX_NO_FLAT_TOOLBAR)?0:wxTB_FLAT)
-                                        /*| wxTB_HORIZONTAL | wxNO_BORDER*/ );
+            long toolBarFlags = ((GetExtraStyle()&wxPG_EX_NO_FLAT_TOOLBAR)?0:wxTB_FLAT);
+            if (GetExtraStyle() & wxPG_EX_NO_TOOLBAR_DIVIDER)
+                toolBarFlags |= wxTB_NODIVIDER;
+
+            m_pToolbar = new wxToolBar(this, wxID_ANY,
+                                       wxDefaultPosition,
+                                       wxDefaultSize,
+                                       toolBarFlags);
             m_pToolbar->SetToolBitmapSize(wxSize(16, 15));
 
         #if defined(__WXMSW__)
             m_pToolbar->SetToolBitmapSize(wxSize(16, 15));
 
         #if defined(__WXMSW__)
@@ -1212,32 +1493,62 @@ void wxPropertyGridManager::RecreateControls()
             {
                 wxString desc1(_("Categorized Mode"));
                 wxString desc2(_("Alphabetic Mode"));
             {
                 wxString desc1(_("Categorized Mode"));
                 wxString desc2(_("Alphabetic Mode"));
-                m_pToolbar->AddTool(baseId+ID_ADVTBITEMSBASE_OFFSET+0,
-                    desc1,wxBitmap ( (const char**)gs_xpm_catmode ),
-                    desc1,wxITEM_RADIO);
-                m_pToolbar->AddTool(baseId+ID_ADVTBITEMSBASE_OFFSET+1,
-                    desc2,wxBitmap ( (const char**)gs_xpm_noncatmode ),
-                    desc2,wxITEM_RADIO);
+
+                wxToolBarToolBase* tool;
+
+                tool = m_pToolbar->AddTool(wxID_ANY,
+                                           desc1,
+                                           wxBitmap(gs_xpm_catmode),
+                                           desc1,
+                                           wxITEM_RADIO);
+                m_categorizedModeToolId = tool->GetId();
+
+                tool = m_pToolbar->AddTool(wxID_ANY,
+                                           desc2,
+                                           wxBitmap(gs_xpm_noncatmode),
+                                           desc2,
+                                           wxITEM_RADIO);
+                m_alphabeticModeToolId = tool->GetId();
+
                 m_pToolbar->Realize();
                 m_pToolbar->Realize();
+
+                Connect(m_categorizedModeToolId,
+                        wxEVT_COMMAND_TOOL_CLICKED,
+                        wxCommandEventHandler(
+                            wxPropertyGridManager::OnToolbarClick));
+                Connect(m_alphabeticModeToolId,
+                        wxEVT_COMMAND_TOOL_CLICKED,
+                        wxCommandEventHandler(
+                            wxPropertyGridManager::OnToolbarClick));
+            }
+            else
+            {
+                m_categorizedModeToolId = -1;
+                m_alphabeticModeToolId = -1;
             }
 
         }
 
             }
 
         }
 
-        if ( (GetExtraStyle()&wxPG_EX_MODE_BUTTONS) )
+        if ( (GetExtraStyle() & wxPG_EX_MODE_BUTTONS) )
         {
             // Toggle correct mode button.
             // TODO: This doesn't work in wxMSW (when changing,
             // both items will get toggled).
         {
             // Toggle correct mode button.
             // TODO: This doesn't work in wxMSW (when changing,
             // both items will get toggled).
-            int toggle_but_on_ind = ID_ADVTBITEMSBASE_OFFSET+0;
-            int toggle_but_off_ind = ID_ADVTBITEMSBASE_OFFSET+1;
+            int toggle_but_on_ind;
+            int toggle_but_off_ind;
             if ( m_pPropGrid->m_pState->IsInNonCatMode() )
             {
             if ( m_pPropGrid->m_pState->IsInNonCatMode() )
             {
-                toggle_but_on_ind++;
-                toggle_but_off_ind--;
+                toggle_but_on_ind = m_alphabeticModeToolId;
+                toggle_but_off_ind = m_categorizedModeToolId;
+            }
+            else
+            {
+                toggle_but_on_ind = m_categorizedModeToolId;
+                toggle_but_off_ind = m_alphabeticModeToolId;
             }
 
             }
 
-            m_pToolbar->ToggleTool(baseId+toggle_but_on_ind,true);
-            m_pToolbar->ToggleTool(baseId+toggle_but_off_ind,false);
+            m_pToolbar->ToggleTool(toggle_but_on_ind, true);
+            m_pToolbar->ToggleTool(toggle_but_off_ind, false);
         }
 
     }
         }
 
     }
@@ -1250,6 +1561,31 @@ void wxPropertyGridManager::RecreateControls()
     }
 #endif
 
     }
 #endif
 
+#if wxUSE_HEADERCTRL
+    if ( m_showHeader )
+    {
+        wxPGHeaderCtrl* hc;
+
+        if ( !m_pHeaderCtrl )
+        {
+            hc = new wxPGHeaderCtrl(this);
+            hc->Create(this, wxID_ANY);
+            m_pHeaderCtrl = hc;
+        }
+        else
+        {
+            m_pHeaderCtrl->Show();
+        }
+
+        m_pHeaderCtrl->OnPageChanged(GetCurrentPage());
+    }
+    else
+    {
+        if ( m_pHeaderCtrl )
+            m_pHeaderCtrl->Hide();
+    }
+#endif
+
     if ( m_windowStyle & wxPG_DESCRIPTION )
     {
         // Has help box.
     if ( m_windowStyle & wxPG_DESCRIPTION )
     {
         // Has help box.
@@ -1258,7 +1594,7 @@ void wxPropertyGridManager::RecreateControls()
         if ( !m_pTxtHelpCaption )
         {
             m_pTxtHelpCaption = new wxStaticText(this,
         if ( !m_pTxtHelpCaption )
         {
             m_pTxtHelpCaption = new wxStaticText(this,
-                                                 baseId+ID_ADVHELPCAPTION_OFFSET,
+                                                 wxID_ANY,
                                                  wxT(""),
                                                  wxDefaultPosition,
                                                  wxDefaultSize,
                                                  wxT(""),
                                                  wxDefaultPosition,
                                                  wxDefaultSize,
@@ -1269,7 +1605,7 @@ void wxPropertyGridManager::RecreateControls()
         if ( !m_pTxtHelpContent )
         {
             m_pTxtHelpContent = new wxStaticText(this,
         if ( !m_pTxtHelpContent )
         {
             m_pTxtHelpContent = new wxStaticText(this,
-                                                 baseId+ID_ADVHELPCONTENT_OFFSET,
+                                                 wxID_ANY,
                                                  wxT(""),
                                                  wxDefaultPosition,
                                                  wxDefaultSize,
                                                  wxT(""),
                                                  wxDefaultPosition,
                                                  wxDefaultSize,
@@ -1342,69 +1678,60 @@ bool wxPropertyGridManager::EnsureVisible( wxPGPropArg id )
 void wxPropertyGridManager::OnToolbarClick( wxCommandEvent &event )
 {
     int id = event.GetId();
 void wxPropertyGridManager::OnToolbarClick( wxCommandEvent &event )
 {
     int id = event.GetId();
-    if ( id >= 0 )
-    {
-        int baseId = m_pPropGrid->GetId();
-        if ( baseId < 0 )
-            baseId = wxPG_MAN_ALTERNATE_BASE_ID;
 
 
-        if ( id == ( baseId + ID_ADVTBITEMSBASE_OFFSET + 0 ) )
+    if ( id == m_categorizedModeToolId )
+    {
+        // Categorized mode.
+        if ( m_pPropGrid->m_windowStyle & wxPG_HIDE_CATEGORIES )
         {
         {
-            // Categorized mode.
-            if ( m_pPropGrid->m_windowStyle & wxPG_HIDE_CATEGORIES )
-            {
-                if ( !m_pPropGrid->HasInternalFlag(wxPG_FL_CATMODE_AUTO_SORT) )
-                    m_pPropGrid->m_windowStyle &= ~wxPG_AUTO_SORT;
-                m_pPropGrid->EnableCategories( true );
-            }
+            if ( !m_pPropGrid->HasInternalFlag(wxPG_FL_CATMODE_AUTO_SORT) )
+                m_pPropGrid->m_windowStyle &= ~wxPG_AUTO_SORT;
+            m_pPropGrid->EnableCategories( true );
         }
         }
-        else if ( id == ( baseId + ID_ADVTBITEMSBASE_OFFSET + 1 ) )
+    }
+    else if ( id == m_alphabeticModeToolId )
+    {
+        // Alphabetic mode.
+        if ( !(m_pPropGrid->m_windowStyle & wxPG_HIDE_CATEGORIES) )
         {
         {
-            // Alphabetic mode.
-            if ( !(m_pPropGrid->m_windowStyle & wxPG_HIDE_CATEGORIES) )
-            {
-                if ( m_pPropGrid->HasFlag(wxPG_AUTO_SORT) )
-                    m_pPropGrid->SetInternalFlag(wxPG_FL_CATMODE_AUTO_SORT);
-                else
-                    m_pPropGrid->ClearInternalFlag(wxPG_FL_CATMODE_AUTO_SORT);
+            if ( m_pPropGrid->HasFlag(wxPG_AUTO_SORT) )
+                m_pPropGrid->SetInternalFlag(wxPG_FL_CATMODE_AUTO_SORT);
+            else
+                m_pPropGrid->ClearInternalFlag(wxPG_FL_CATMODE_AUTO_SORT);
 
 
-                m_pPropGrid->m_windowStyle |= wxPG_AUTO_SORT;
-                m_pPropGrid->EnableCategories( false );
-            }
+            m_pPropGrid->m_windowStyle |= wxPG_AUTO_SORT;
+            m_pPropGrid->EnableCategories( false );
         }
         }
-        else
-        {
-            // Page Switching.
+    }
+    else
+    {
+        // Page Switching.
 
 
-            int index = -1;
-            size_t i;
-            wxPropertyGridPage* pdc;
+        int index = -1;
+        size_t i;
+        wxPropertyGridPage* pdc;
 
 
-            // Find page with given id.
-            for ( i=0; i<GetPageCount(); i++ )
+        // Find page with given id.
+        for ( i=0; i<GetPageCount(); i++ )
+        {
+            pdc = m_arrPages[i];
+            if ( pdc->m_toolId == id )
             {
             {
-                pdc = m_arrPages[i];
-                if ( pdc->m_id == id )
-                {
-                    index = i;
-                    break;
-                }
+                index = i;
+                break;
             }
             }
+        }
 
 
-            wxASSERT( index >= 0 );
-
-            if ( DoSelectPage( index ) )
-            {
-
-                // Event dispatching must be last.
-                m_pPropGrid->SendEvent(  wxEVT_PG_PAGE_CHANGED, NULL );
-
-            }
-            else
-            {
-                // TODO: Depress the old button on toolbar.
-            }
+        wxASSERT( index >= 0 );
 
 
+        if ( DoSelectPage( index ) )
+        {
+            // Event dispatching must be last.
+            m_pPropGrid->SendEvent(  wxEVT_PG_PAGE_CHANGED, NULL );
+        }
+        else
+        {
+            // TODO: Depress the old button on toolbar.
         }
     }
 }
         }
     }
 }
@@ -1479,7 +1806,7 @@ void wxPropertyGridManager::SetSplitterLeft( bool subProps, bool allPages )
     else
     {
         wxClientDC dc(this);
     else
     {
         wxClientDC dc(this);
-        dc.SetFont(m_pPropGrid->m_font);
+        dc.SetFont(m_pPropGrid->GetFont());
 
         int highest = 0;
         unsigned int i;
 
         int highest = 0;
         unsigned int i;
@@ -1490,13 +1817,17 @@ void wxPropertyGridManager::SetSplitterLeft( bool subProps, bool allPages )
             maxW += m_pPropGrid->m_marginWidth;
             if ( maxW > highest )
                 highest = maxW;
             maxW += m_pPropGrid->m_marginWidth;
             if ( maxW > highest )
                 highest = maxW;
+            m_pState->m_dontCenterSplitter = true;
         }
 
         if ( highest > 0 )
             m_pPropGrid->SetSplitterPosition( highest );
         }
 
         if ( highest > 0 )
             m_pPropGrid->SetSplitterPosition( highest );
-
-        m_pPropGrid->m_iFlags |= wxPG_FL_DONT_CENTER_SPLITTER;
     }
     }
+
+#if wxUSE_HEADERCTRL
+    if ( m_showHeader )
+        m_pHeaderCtrl->OnColumWidthsChanged();
+#endif
 }
 
 // -----------------------------------------------------------------------
 }
 
 // -----------------------------------------------------------------------
@@ -1513,16 +1844,47 @@ void wxPropertyGridManager::OnPropertyGridSelect( wxPropertyGridEvent& event )
 
 // -----------------------------------------------------------------------
 
 
 // -----------------------------------------------------------------------
 
+void
+wxPropertyGridManager::OnPGColDrag( wxPropertyGridEvent& WXUNUSED(event) )
+{
+#if wxUSE_HEADERCTRL
+    if ( !m_showHeader )
+        return;
+
+    m_pHeaderCtrl->OnColumWidthsChanged();
+#endif
+}
+
+// -----------------------------------------------------------------------
+
 void wxPropertyGridManager::OnResize( wxSizeEvent& WXUNUSED(event) )
 {
     int width, height;
 
 void wxPropertyGridManager::OnResize( wxSizeEvent& WXUNUSED(event) )
 {
     int width, height;
 
-    GetClientSize(&width,&height);
+    GetClientSize(&width, &height);
 
     if ( m_width == -12345 )
         RecreateControls();
 
 
     if ( m_width == -12345 )
         RecreateControls();
 
-    RecalculatePositions(width,height);
+    RecalculatePositions(width, height);
+
+    if ( m_pPropGrid && m_pPropGrid->m_parent )
+    {
+        int pgWidth, pgHeight;
+        m_pPropGrid->GetClientSize(&pgWidth, &pgHeight);
+
+        // Regenerate splitter positions for non-current pages
+        for ( unsigned int i=0; i<GetPageCount(); i++ )
+        {
+            wxPropertyGridPage* page = GetPage(i);
+            if ( page != m_pPropGrid->GetState() )
+            {
+                page->OnClientWidthChange(pgWidth,
+                                          pgWidth - page->m_width,
+                                          true);
+            }
+        }
+    }
 }
 
 // -----------------------------------------------------------------------
 }
 
 // -----------------------------------------------------------------------
@@ -1659,10 +2021,28 @@ void wxPropertyGridManager::SetSplitterPosition( int pos, int splitterColumn )
     for ( i=0; i<GetPageCount(); i++ )
     {
         wxPropertyGridPage* page = GetPage(i);
     for ( i=0; i<GetPageCount(); i++ )
     {
         wxPropertyGridPage* page = GetPage(i);
-        page->DoSetSplitterPosition( pos, splitterColumn, false );
+        page->DoSetSplitterPosition( pos, splitterColumn,
+                                     wxPG_SPLITTER_REFRESH );
     }
 
     }
 
-    m_pPropGrid->SetInternalFlag(wxPG_FL_SPLITTER_PRE_SET);
+#if wxUSE_HEADERCTRL
+    if ( m_showHeader )
+        m_pHeaderCtrl->OnColumWidthsChanged();
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void wxPropertyGridManager::SetPageSplitterPosition( int page,
+                                                     int pos,
+                                                     int column )
+{
+    GetPage(page)->DoSetSplitterPosition( pos, column );
+
+#if wxUSE_HEADERCTRL
+    if ( m_showHeader )
+        m_pHeaderCtrl->OnColumWidthsChanged();
+#endif
 }
 
 // -----------------------------------------------------------------------
 }
 
 // -----------------------------------------------------------------------