]> git.saurik.com Git - wxWidgets.git/commitdiff
Most of FM's wxDataViewCtrl patch.
authorRobert Roebling <robert@roebling.de>
Sat, 17 Feb 2007 12:32:38 +0000 (12:32 +0000)
committerRobert Roebling <robert@roebling.de>
Sat, 17 Feb 2007 12:32:38 +0000 (12:32 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@44523 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/dataview.h
include/wx/generic/dataview.h
include/wx/gtk/dataview.h
samples/dataview/dataview.cpp
src/common/datavcmn.cpp
src/generic/datavgen.cpp
src/gtk/dataview.cpp

index 8893378606869814cfa0844e992e3e71e236cff7..d255228773d82bcf7198645c77487c9d562a4ca1 100644 (file)
@@ -47,25 +47,31 @@ class WXDLLIMPEXP_ADV wxDataViewRenderer;
 
 extern WXDLLIMPEXP_DATA_ADV(const wxChar) wxDataViewCtrlNameStr[];
 
+// the default width of new (text) columns:
+#define wxDVC_DEFAULT_WIDTH             80
+
+// the default width of new toggle columns:
+#define wxDVC_TOGGLE_DEFAULT_WIDTH      30
+
+
 // ---------------------------------------------------------
 // wxDataViewModel
 // ---------------------------------------------------------
 
-class WXDLLIMPEXP_ADV wxDataViewModel: public wxObject
+class WXDLLIMPEXP_ADV wxDataViewModel: public wxObjectRefData
 {
 public:
     wxDataViewModel() { }
-    virtual ~wxDataViewModel() { }
 
 protected:
-    DECLARE_DYNAMIC_CLASS_NO_COPY(wxDataViewModel)
+    // the user should not delete this class directly: he should use DecRef() instead!
+    virtual ~wxDataViewModel() { }
 };
 
 // ---------------------------------------------------------
 // wxDataViewListModelNotifier
 // ---------------------------------------------------------
 
-
 class WXDLLIMPEXP_ADV wxDataViewListModelNotifier: public wxObject
 {
 public:
@@ -80,6 +86,8 @@ public:
     virtual bool ValueChanged( unsigned int col, unsigned int row ) = 0;
     virtual bool RowsReordered( unsigned int *new_order ) = 0;
     virtual bool Cleared() = 0;
+    virtual bool Freed()
+        { m_owner = NULL; return true; }
 
     void SetOwner( wxDataViewListModel *owner ) { m_owner = owner; }
     wxDataViewListModel *GetOwner()             { return m_owner; }
@@ -107,16 +115,24 @@ public:
 
 class WXDLLIMPEXP_ADV wxDataViewListModel: public wxDataViewModel
 {
+    friend class WXDLLIMPEXP_ADV wxDataViewCtrl;
+    friend class WXDLLIMPEXP_ADV wxDataViewCtrlBase;
+    friend class WXDLLIMPEXP_ADV wxDataViewSortedListModel;
+    friend class WXDLLIMPEXP_ADV wxDataViewColumnBase;
+    friend class WXDLLIMPEXP_ADV wxGtkDataViewListModelNotifier;
+
 public:
     wxDataViewListModel();
-    virtual ~wxDataViewListModel();
 
     virtual unsigned int GetNumberOfRows() = 0;
     virtual unsigned int GetNumberOfCols() = 0;
+
     // return type as reported by wxVariant
     virtual wxString GetColType( unsigned int col ) = 0;
+
     // get value into a wxVariant
     virtual void GetValue( wxVariant &variant, unsigned int col, unsigned int row ) = 0;
+
     // set value, call ValueChanged() afterwards!
     virtual bool SetValue( wxVariant &variant, unsigned int col, unsigned int row ) = 0;
 
@@ -130,6 +146,10 @@ public:
     virtual bool RowsReordered( unsigned int *new_order );
     virtual bool Cleared();
 
+protected:
+    // the user should not delete this class directly: he should use DecRef() instead!
+    virtual ~wxDataViewListModel();
+
     // Used internally
     void AddViewingColumn( wxDataViewColumn *view_column, unsigned int model_column );
     void RemoveViewingColumn( wxDataViewColumn *column );
@@ -139,11 +159,10 @@ public:
 
     wxList                      m_notifiers;
     wxList                      m_viewingColumns;
-
-protected:
-    DECLARE_DYNAMIC_CLASS_NO_COPY(wxDataViewListModel)
 };
 
+
+
 // ---------------------------------------------------------
 // wxDataViewSortedListModel
 // ---------------------------------------------------------
@@ -155,6 +174,8 @@ WX_DEFINE_SORTED_USER_EXPORTED_ARRAY_SIZE_T(unsigned int, wxDataViewSortedIndexA
 
 class WXDLLIMPEXP_ADV wxDataViewSortedListModel: public wxDataViewListModel
 {
+    friend class wxDataViewSortedListModelNotifier;
+
 public:
     wxDataViewSortedListModel( wxDataViewListModel *child );
     virtual ~wxDataViewSortedListModel();
@@ -200,9 +221,6 @@ private:
     wxDataViewListModelNotifier     *m_notifierOnChild;
     
     void InitStatics(); // BAD
-
-protected:
-    DECLARE_DYNAMIC_CLASS_NO_COPY(wxDataViewSortedListModel)
 };
 
 // ---------------------------------------------------------
@@ -262,10 +280,14 @@ enum wxDataViewColumnFlags
 class WXDLLIMPEXP_ADV wxDataViewColumnBase: public wxObject
 {
 public:
-    wxDataViewColumnBase( const wxString &title, wxDataViewRenderer *renderer, unsigned int model_column,
-        int width = 80, int flags = wxDATAVIEW_COL_RESIZABLE );
-    wxDataViewColumnBase( const wxBitmap &bitmap, wxDataViewRenderer *renderer, unsigned int model_column,
-        int width = 80, int flags = wxDATAVIEW_COL_RESIZABLE );
+    wxDataViewColumnBase( const wxString &title, wxDataViewRenderer *renderer, 
+                          unsigned int model_column, int width = wxDVC_DEFAULT_WIDTH, 
+                          wxAlignment align = wxALIGN_CENTER,
+                          int flags = wxDATAVIEW_COL_RESIZABLE );
+    wxDataViewColumnBase( const wxBitmap &bitmap, wxDataViewRenderer *renderer, 
+                          unsigned int model_column, int width = wxDVC_DEFAULT_WIDTH, 
+                          wxAlignment align = wxALIGN_CENTER,
+                          int flags = wxDATAVIEW_COL_RESIZABLE );
     virtual ~wxDataViewColumnBase();
 
     virtual void SetTitle( const wxString &title );
@@ -277,9 +299,15 @@ public:
     virtual void SetAlignment( wxAlignment align ) = 0;
     
     virtual void SetSortable( bool sortable ) = 0;
-    virtual bool GetSortable() = 0;
+    virtual bool IsSortable() const
+        { return (m_flags & wxDATAVIEW_COL_SORTABLE) != 0; }
+    virtual bool IsResizeable() const
+        { return (m_flags & wxDATAVIEW_COL_RESIZABLE) != 0; }
+    virtual bool IsHidden() const
+        { return (m_flags & wxDATAVIEW_COL_HIDDEN) != 0; }
+
     virtual void SetSortOrder( bool ascending ) = 0;
-    virtual bool IsSortOrderAscending() = 0;
+    virtual bool IsSortOrderAscending() const = 0;
 
     wxDataViewRenderer* GetRenderer()       { return m_renderer; }
 
@@ -288,7 +316,7 @@ public:
     virtual void SetOwner( wxDataViewCtrl *owner )  { m_owner = owner; }
     wxDataViewCtrl *GetOwner()              { return m_owner; }
 
-    virtual int GetWidth() = 0;
+    virtual int GetWidth() const = 0;
 
 private:
     wxDataViewCtrl          *m_ctrl;
@@ -321,25 +349,45 @@ public:
 
     // short cuts
     bool AppendTextColumn( const wxString &label, unsigned int model_column, 
-                    wxDataViewCellMode mode = wxDATAVIEW_CELL_INERT, int width = -1 );
+                    wxDataViewCellMode mode = wxDATAVIEW_CELL_INERT, int width = -1,
+                    wxAlignment align = wxALIGN_CENTER,
+                    int flags = wxDATAVIEW_COL_RESIZABLE );
     bool AppendToggleColumn( const wxString &label, unsigned int model_column,
-                    wxDataViewCellMode mode = wxDATAVIEW_CELL_INERT, int width = 30 );
+                    wxDataViewCellMode mode = wxDATAVIEW_CELL_INERT, int width = wxDVC_TOGGLE_DEFAULT_WIDTH,
+                    wxAlignment align = wxALIGN_CENTER,
+                    int flags = wxDATAVIEW_COL_RESIZABLE );
     bool AppendProgressColumn( const wxString &label, unsigned int model_column, 
-                    wxDataViewCellMode mode = wxDATAVIEW_CELL_INERT, int width = 80 );
+                    wxDataViewCellMode mode = wxDATAVIEW_CELL_INERT, int width = wxDVC_DEFAULT_WIDTH,
+                    wxAlignment align = wxALIGN_CENTER,
+                    int flags = wxDATAVIEW_COL_RESIZABLE );
     bool AppendDateColumn( const wxString &label, unsigned int model_column,
-                    wxDataViewCellMode mode = wxDATAVIEW_CELL_ACTIVATABLE, int width = -1 );
+                    wxDataViewCellMode mode = wxDATAVIEW_CELL_ACTIVATABLE, int width = -1,
+                    wxAlignment align = wxALIGN_CENTER,
+                    int flags = wxDATAVIEW_COL_RESIZABLE );
     bool AppendBitmapColumn( const wxString &label, unsigned int model_column,
-                    wxDataViewCellMode mode = wxDATAVIEW_CELL_INERT, int width = -1 );
+                    wxDataViewCellMode mode = wxDATAVIEW_CELL_INERT, int width = -1,
+                    wxAlignment align = wxALIGN_CENTER,
+                    int flags = wxDATAVIEW_COL_RESIZABLE );
     bool AppendTextColumn( const wxBitmap &label, unsigned int model_column,
-                    wxDataViewCellMode mode = wxDATAVIEW_CELL_INERT, int width = -1 );
+                    wxDataViewCellMode mode = wxDATAVIEW_CELL_INERT, int width = -1,
+                    wxAlignment align = wxALIGN_CENTER,
+                    int flags = wxDATAVIEW_COL_RESIZABLE );
     bool AppendToggleColumn( const wxBitmap &label, unsigned int model_column,
-                    wxDataViewCellMode mode = wxDATAVIEW_CELL_INERT, int width = 30 );
+                    wxDataViewCellMode mode = wxDATAVIEW_CELL_INERT, int width = wxDVC_TOGGLE_DEFAULT_WIDTH,
+                    wxAlignment align = wxALIGN_CENTER,
+                    int flags = wxDATAVIEW_COL_RESIZABLE );
     bool AppendProgressColumn( const wxBitmap &label, unsigned int model_column,
-                    wxDataViewCellMode mode = wxDATAVIEW_CELL_INERT, int width = 80 );
+                    wxDataViewCellMode mode = wxDATAVIEW_CELL_INERT, int width = wxDVC_DEFAULT_WIDTH,
+                    wxAlignment align = wxALIGN_CENTER,
+                    int flags = wxDATAVIEW_COL_RESIZABLE );
     bool AppendDateColumn( const wxBitmap &label, unsigned int model_column,
-                    wxDataViewCellMode mode = wxDATAVIEW_CELL_ACTIVATABLE, int width = -1 );
+                    wxDataViewCellMode mode = wxDATAVIEW_CELL_ACTIVATABLE, int width = -1,
+                    wxAlignment align = wxALIGN_CENTER,
+                    int flags = wxDATAVIEW_COL_RESIZABLE );
     bool AppendBitmapColumn( const wxBitmap &label, unsigned int model_column,
-                    wxDataViewCellMode mode = wxDATAVIEW_CELL_INERT, int width = -1 );
+                    wxDataViewCellMode mode = wxDATAVIEW_CELL_INERT, int width = -1,
+                    wxAlignment align = wxALIGN_CENTER,
+                    int flags = wxDATAVIEW_COL_RESIZABLE );
     
     virtual bool AppendColumn( wxDataViewColumn *col );
     virtual unsigned int GetNumberOfColumns();
index a8800e37aa73e291d9c83f0bb1add01390b2bea6..0a96c88b3f81b14ff99b8e7f52579e70cef97a83 100644 (file)
@@ -32,7 +32,8 @@ class WXDLLIMPEXP_ADV wxDataViewHeaderWindow;
 class WXDLLIMPEXP_ADV wxDataViewRenderer: public wxDataViewRendererBase
 {
 public:
-    wxDataViewRenderer( const wxString &varianttype, wxDataViewCellMode mode = wxDATAVIEW_CELL_INERT );
+    wxDataViewRenderer( const wxString &varianttype, 
+                        wxDataViewCellMode mode = wxDATAVIEW_CELL_INERT );
     virtual ~wxDataViewRenderer();
 
     virtual bool Render( wxRect cell, wxDC *dc, int state ) = 0;
@@ -148,7 +149,8 @@ public:
     bool GetValue( wxVariant &value );
 
     bool Render( wxRect cell, wxDC *dc, int state );
-    bool Activate( wxRect cell, wxDataViewListModel *model, unsigned int col, unsigned int row );
+    bool Activate( wxRect cell, wxDataViewListModel *model, unsigned int col, 
+                   unsigned int row );
     wxSize GetSize();
 
 private:
@@ -213,28 +215,46 @@ protected:
 
 class WXDLLIMPEXP_ADV wxDataViewColumn: public wxDataViewColumnBase
 {
+    friend class wxDataViewHeaderWindowBase;
+    friend class wxDataViewHeaderWindow;
+    friend class wxDataViewHeaderWindowMSW;
+
 public:
-    wxDataViewColumn( const wxString &title, wxDataViewRenderer *renderer, unsigned int model_column, 
-        int width = 80, int flags = wxDATAVIEW_COL_RESIZABLE );
-    wxDataViewColumn( const wxBitmap &bitmap, wxDataViewRenderer *renderer, unsigned int model_column,
-        int width = 80, int flags = wxDATAVIEW_COL_RESIZABLE );
+    wxDataViewColumn( const wxString &title, wxDataViewRenderer *renderer, 
+                      unsigned int model_column, int width = wxDVC_DEFAULT_WIDTH, 
+                      wxAlignment align = wxALIGN_CENTER,
+                      int flags = wxDATAVIEW_COL_RESIZABLE );
+    wxDataViewColumn( const wxBitmap &bitmap, wxDataViewRenderer *renderer, 
+                      unsigned int model_column, int width = wxDVC_DEFAULT_WIDTH, 
+                      wxAlignment align = wxALIGN_CENTER,
+                      int flags = wxDATAVIEW_COL_RESIZABLE );
     virtual ~wxDataViewColumn();
 
     virtual void SetTitle( const wxString &title );
     virtual void SetBitmap( const wxBitmap &bitmap );
     
-    virtual void SetAlignment( wxAlignment align );
+    virtual void SetAlignment( wxAlignment align )
+        { m_align=align; }
+    wxAlignment GetAlignment() const
+        { return m_align; }
     
     virtual void SetSortable( bool sortable );
-    virtual bool GetSortable();
     virtual void SetSortOrder( bool ascending );
-    virtual bool IsSortOrderAscending();
+    virtual bool IsSortOrderAscending() const;
+
+    virtual int GetWidth() const;
+
+protected:
 
-    virtual int GetWidth();
+    void SetWidth(int w)
+        { m_width=w; }
 
 private:
     int                      m_width;
     int                      m_fixedWidth;
+    wxAlignment m_align;
+
+    void Init(int width);
 
 protected:
     DECLARE_DYNAMIC_CLASS_NO_COPY(wxDataViewColumn)
@@ -247,6 +267,11 @@ protected:
 class WXDLLIMPEXP_ADV wxDataViewCtrl: public wxDataViewCtrlBase,
                                        public wxScrollHelperNative
 {
+    friend class wxDataViewMainWindow;
+    friend class wxDataViewHeaderWindowBase;
+    friend class wxDataViewHeaderWindow;
+    friend class wxDataViewHeaderWindowMSW;
+
 public:
     wxDataViewCtrl() : wxScrollHelperNative(this)
     {
@@ -283,9 +308,14 @@ public:
     virtual int GetSelection() const;
     virtual int GetSelections(wxArrayInt& aSelections) const;
 
+    // returns the "best" width for the idx-th column
+    unsigned int GetBestColumnWidth(int WXUNUSED(idx))
+    {
+        return GetClientSize().GetWidth() / GetNumberOfColumns();
+    }
+
+
 private:
-    friend class wxDataViewMainWindow;
-    friend class wxDataViewHeaderWindow;
     wxDataViewListModelNotifier *m_notifier;
     wxDataViewMainWindow        *m_clientArea;
     wxDataViewHeaderWindow      *m_headerArea;
index e575a4f2c087c8e9d46f1d2a261d806667597789..78ddb1d55bf2c7c479eaca4114a0de3502ca85d4 100644 (file)
@@ -21,6 +21,7 @@
 
 class WXDLLIMPEXP_CORE wxDataViewCtrl;
 
+
 // --------------------------------------------------------- 
 // wxDataViewRenderer
 // --------------------------------------------------------- 
@@ -28,7 +29,8 @@ class WXDLLIMPEXP_CORE wxDataViewCtrl;
 class wxDataViewRenderer: public wxDataViewRendererBase
 {
 public:
-    wxDataViewRenderer( const wxString &varianttype, wxDataViewCellMode mode = wxDATAVIEW_CELL_INERT );
+    wxDataViewRenderer( const wxString &varianttype, 
+                        wxDataViewCellMode mode = wxDATAVIEW_CELL_INERT );
 
     // implementation
     void* GetGtkHandle() { return m_renderer; }
@@ -188,10 +190,15 @@ protected:
 class WXDLLIMPEXP_CORE wxDataViewColumn: public wxDataViewColumnBase
 {
 public:
-    wxDataViewColumn( const wxString &title, wxDataViewRenderer *renderer, unsigned int model_column,
-        int width = 80, int flags = wxDATAVIEW_COL_RESIZABLE );
-    wxDataViewColumn( const wxBitmap &bitmap, wxDataViewRenderer *renderer, unsigned int model_column,
-        int width = 80, int flags = wxDATAVIEW_COL_RESIZABLE );
+    wxDataViewColumn( const wxString &title, wxDataViewRenderer *renderer,
+                      unsigned int model_column, int width = wxDVC_DEFAULT_WIDTH,
+                      wxAlignment align = wxALIGN_CENTER,
+                      int flags = wxDATAVIEW_COL_RESIZABLE );
+    wxDataViewColumn( const wxBitmap &bitmap, wxDataViewRenderer *renderer,
+                      unsigned int model_column, int width = wxDVC_DEFAULT_WIDTH,
+                      wxAlignment align = wxALIGN_CENTER,
+                      int flags = wxDATAVIEW_COL_RESIZABLE );
+
     virtual ~wxDataViewColumn();
 
     virtual void SetTitle( const wxString &title );
@@ -202,14 +209,15 @@ public:
     virtual void SetAlignment( wxAlignment align );
     
     virtual void SetSortable( bool sortable );
-    virtual bool GetSortable();
     virtual void SetSortOrder( bool ascending );
-    virtual bool IsSortOrderAscending();
 
-    virtual int GetWidth();
+    virtual bool IsSortable() const;
+    virtual bool IsSortOrderAscending() const;
+
+    virtual int GetWidth() const;
     
     virtual void SetFixedWidth( int width );
-    virtual int GetFixedWidth();
+    virtual int GetFixedWidth() const;
     
     // implementation
     void* GetGtkHandle() { return m_column; }
index a8e6d7935a9f74334dcda927618da571431236c5..dd44fadb32b0304964e19eaa366e2c9d27310107 100644 (file)
@@ -21,6 +21,8 @@
 #endif
 
 #include "wx/datetime.h"
+#include "wx/splitter.h"
+#include "wx/aboutdlg.h"
 
 #ifndef __WXMSW__
     #include "../sample.xpm"
@@ -34,9 +36,9 @@
 // MyTextModel
 // -------------------------------------
 
-WX_DECLARE_LIST(wxDateTime,wxArrayDate);
-#include <wx/listimpl.cpp>
-WX_DEFINE_LIST(wxArrayDate)
+WX_DECLARE_OBJARRAY(wxDateTime,wxArrayDate);
+#include <wx/arrimpl.cpp>
+WX_DEFINE_OBJARRAY(wxArrayDate)
 
 class MyTextModel: public wxDataViewListModel
 {
@@ -54,8 +56,8 @@ public:
             { m_progress.Add( i/10 ); }
         for (i = 0; i < 1000; i++)
             {
-                wxDateTime *date = new wxDateTime( wxDateTime::Now() );
-                m_dates.Append( date );
+                wxDateTime date( wxDateTime::Now() );
+                m_dates.Add( date );
             }
     }
 
@@ -83,7 +85,7 @@ public:
         {
             if (col == 6)
             {
-                variant = (wxDateTime) *m_dates[row];
+                variant = (wxDateTime) m_dates[row];
             } else
             if (col == 5)
             {
@@ -95,7 +97,7 @@ public:
             } else
             if (col == 3)
             {
-                variant = (bool) m_bools[row];
+                variant = (bool) (m_bools[row] != 0);
             } else
             if (col == 2)
             {
@@ -112,7 +114,7 @@ public:
         {
             if (col == 6)
             {
-                *m_dates[row] = value.GetDateTime();
+                m_dates[row] = value.GetDateTime();
             } else
             if (col == 3)
             {
@@ -263,13 +265,14 @@ class MyApp: public wxApp
 {
 public:
     bool OnInit(void);
+    int OnExit();
 };
 
 // -------------------------------------
 // MyFrame
 // -------------------------------------
 
-class MyFrame: public wxFrame
+class MyFrame : public wxFrame
 {
 public:
     MyFrame(wxFrame *frame, wxChar *title, int x, int y, int w, int h);
@@ -277,10 +280,26 @@ public:
 public:
     void OnQuit(wxCommandEvent& event);
     void OnAbout(wxCommandEvent& event);
+    void OnNewSortingFrame(wxCommandEvent& event);
+
+    void OnSingleSelMode(wxCommandEvent& event);
+    void OnMultipleSelMode(wxCommandEvent& event);
+    void OnResizeableColumn(wxCommandEvent& event);
+    void OnSortableColumn(wxCommandEvent& event);
+    void OnHideColumn(wxCommandEvent& event);
+    void OnChooseAlign(wxCommandEvent& event);
 
 private:
     wxDataViewCtrl* dataview_left;
     wxDataViewCtrl* dataview_right;
+    wxSplitterWindow *m_splitter;
+
+    wxAlignment m_align;
+
+    void CreateControls();
+
+private:
+    DECLARE_EVENT_TABLE()
 };
 
 // -------------------------------------
@@ -358,80 +377,174 @@ private:
 // MyApp
 // -------------------------------------
 
-#define DYNAMIC_QUIT   wxID_EXIT
-#define DYNAMIC_ABOUT  wxID_ABOUT
-
-IMPLEMENT_APP  (MyApp)
+IMPLEMENT_APP(MyApp)
 
 bool MyApp::OnInit(void)
 {
     if ( !wxApp::OnInit() )
         return false;
 
-    MyFrame *frame = new MyFrame(NULL, wxT("wxDataViewCtrl feature test"), 10, 10, 800, 340);
+    // build the first frame
+    MyFrame *frame = 
+        new MyFrame(NULL, wxT("wxDataViewCtrl feature test"), 10, 10, 800, 340);
     frame->Show(true);
 
-    MySortingFrame *frame2 = new MySortingFrame(NULL, wxT("wxDataViewCtrl sorting test"), 10, 150, 600, 500);
-    frame2->Show(true);
-
     SetTopWindow(frame);
-    
     return true;
 }
 
+int MyApp::OnExit()
+{
+    return 0;
+}
+
+
 // -------------------------------------
 // MyFrame
 // -------------------------------------
 
+enum
+{
+    // file menu
+    ID_ABOUT = wxID_ABOUT,
+    ID_NEW_SORT_FRAME,
+    ID_EXIT = wxID_EXIT,
+
+    // dataviewctrl menu
+    ID_SINGLE_SEL_MODE,
+    ID_MULTIPLE_SEL_MODE,
+
+    ID_RESIZEABLE_COLUMNS,
+    ID_SORTABLE_COLUMNS,
+    ID_HIDDEN_COLUMNS,
+
+    ID_CHOOSE_ALIGNMENT
+};
+
+BEGIN_EVENT_TABLE(MyFrame, wxFrame)
+
+    // file menu
+    EVT_MENU( ID_ABOUT, MyFrame::OnAbout )
+    EVT_MENU( ID_NEW_SORT_FRAME, MyFrame::OnNewSortingFrame )
+    EVT_MENU( ID_EXIT, MyFrame::OnQuit )
+
+    // dataviewctrl menu
+    EVT_MENU( ID_SINGLE_SEL_MODE, MyFrame::OnSingleSelMode )
+    EVT_MENU( ID_MULTIPLE_SEL_MODE, MyFrame::OnMultipleSelMode )
+
+    EVT_MENU( ID_RESIZEABLE_COLUMNS, MyFrame::OnResizeableColumn )
+    EVT_MENU( ID_SORTABLE_COLUMNS, MyFrame::OnSortableColumn )
+    EVT_MENU( ID_HIDDEN_COLUMNS, MyFrame::OnHideColumn )
+
+    EVT_MENU( ID_CHOOSE_ALIGNMENT, MyFrame::OnChooseAlign )
+
+END_EVENT_TABLE()
+
 MyFrame::MyFrame(wxFrame *frame, wxChar *title, int x, int y, int w, int h):
   wxFrame(frame, wxID_ANY, title, wxPoint(x, y), wxSize(w, h))
 {
     SetIcon(wxICON(sample));
 
+    // build the menus:
+
     wxMenu *file_menu = new wxMenu;
+    file_menu->Append(ID_NEW_SORT_FRAME, _T("&New sorting frame"));
+    file_menu->AppendSeparator();
+    file_menu->Append(ID_ABOUT, _T("&About"));
+    file_menu->AppendSeparator();
+    file_menu->Append(ID_EXIT, _T("E&xit"));
+
+    wxMenu *data_menu = new wxMenu;
+    data_menu->AppendRadioItem(ID_SINGLE_SEL_MODE, _T("&Single selection mode"));
+    data_menu->AppendRadioItem(ID_MULTIPLE_SEL_MODE, _T("&Multiple selection mode"));
+    data_menu->AppendSeparator();
+    data_menu->AppendCheckItem(ID_RESIZEABLE_COLUMNS, _T("Make columns resizeable"));
+    data_menu->AppendCheckItem(ID_SORTABLE_COLUMNS, _T("Make columns sortable"));
+    data_menu->AppendCheckItem(ID_HIDDEN_COLUMNS, _T("Make columns hidden"));
+    data_menu->AppendSeparator();
+    data_menu->Append(ID_CHOOSE_ALIGNMENT, _T("Set alignment..."));
 
-    file_menu->Append(DYNAMIC_ABOUT, _T("&About"));
-    file_menu->Append(DYNAMIC_QUIT, _T("E&xit"));
     wxMenuBar *menu_bar = new wxMenuBar;
     menu_bar->Append(file_menu, _T("&File"));
+    menu_bar->Append(data_menu, _T("&DataViewCtrl"));
+
     SetMenuBar(menu_bar);
+    CreateStatusBar();
 
-    // You used to have to do some casting for param 4, but now there are type-safe handlers
-    Connect( DYNAMIC_QUIT,  wxID_ANY,
-                    wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MyFrame::OnQuit) );
-    Connect( DYNAMIC_ABOUT, wxID_ANY,
-                    wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MyFrame::OnAbout) );
 
-    CreateStatusBar();
+    // build the other controls:
 
-    wxPanel *panel = new wxPanel( this, wxID_ANY );
+    m_splitter = new wxSplitterWindow( this, wxID_ANY );
+    m_splitter->SetSashGravity(0.5);
+
+    m_align = wxALIGN_CENTER;
+    dataview_left = dataview_right = NULL;
+    CreateControls();
+
+    m_splitter->SplitVertically(dataview_left, dataview_right);
+}
+
+void MyFrame::CreateControls()
+{
+    wxDataViewCtrl *old1 = NULL, *old2 = NULL;
+
+    if (dataview_left)
+        old1 = dataview_left;
+    if (dataview_right)
+        old2 = dataview_right;
+
+    // styles:
+
+    long style = 0;
+    if (GetMenuBar()->FindItem(ID_MULTIPLE_SEL_MODE)->IsChecked())
+        style |= wxDV_MULTIPLE;
+
+    int flags = 0;
+    if (GetMenuBar()->FindItem(ID_RESIZEABLE_COLUMNS)->IsChecked())
+        flags |= wxDATAVIEW_COL_RESIZABLE;
+    if (GetMenuBar()->FindItem(ID_SORTABLE_COLUMNS)->IsChecked())
+        flags |= wxDATAVIEW_COL_SORTABLE;
+    if (GetMenuBar()->FindItem(ID_HIDDEN_COLUMNS)->IsChecked())
+        flags |= wxDATAVIEW_COL_HIDDEN;
 
 
     // Left wxDataViewCtrl
-    dataview_left = new wxDataViewCtrl( panel, wxID_ANY );
+    dataview_left = new wxDataViewCtrl( m_splitter, wxID_ANY, wxDefaultPosition,
+                                        wxDefaultSize, style );
 
     MyTextModel *model = new MyTextModel;
     dataview_left->AssociateModel( model );
+    model->DecRef(); // don't leak memory
 
-    dataview_left->AppendTextColumn( wxT("first"), 0 );
-    dataview_left->AppendTextColumn( wxT("second"), 1 );
+    dataview_left->AppendTextColumn( wxT("first"), 0, wxDATAVIEW_CELL_INERT, -1, 
+                                     m_align, flags );
+    dataview_left->AppendTextColumn( wxT("second"), 1, wxDATAVIEW_CELL_INERT, -1, 
+                                     m_align, flags );
 
-    wxDataViewTextRenderer *text_renderer = new wxDataViewTextRenderer( wxT("string"), wxDATAVIEW_CELL_EDITABLE );
-    wxDataViewColumn *column = new wxDataViewColumn( wxT("editable"), text_renderer, 2 );
+    wxDataViewTextRenderer *text_renderer = 
+        new wxDataViewTextRenderer( wxT("string"), wxDATAVIEW_CELL_EDITABLE );
+    wxDataViewColumn *column = new wxDataViewColumn( wxT("editable"), text_renderer, 2,
+                                                     -1, m_align, flags );
     dataview_left->AppendColumn( column );
 
-    dataview_left->AppendToggleColumn( wxT("fourth"), 3 );
+    dataview_left->AppendToggleColumn( wxT("fourth"), 3, wxDATAVIEW_CELL_INERT, -1,  
+                                       m_align, flags );
 
     MyCustomRenderer *custom_renderer = new MyCustomRenderer;
-    column = new wxDataViewColumn( wxT("custom"), custom_renderer, 4 );
+    column = new wxDataViewColumn( wxT("custom"), custom_renderer, 4, -1,  
+                                   m_align, flags );
     dataview_left->AppendColumn( column );
 
-    dataview_left->AppendProgressColumn( wxT("progress"), 5 );
+    dataview_left->AppendProgressColumn( wxT("progress"), 5, wxDATAVIEW_CELL_INERT, -1,  
+                                         m_align, flags );
+
+    dataview_left->AppendDateColumn( wxT("date"), 6, wxDATAVIEW_CELL_INERT, -1,  
+                                     m_align, flags );
 
-    dataview_left->AppendDateColumn( wxT("date"), 6 );
 
     // Right wxDataViewCtrl using the same model
-    dataview_right = new wxDataViewCtrl( panel, wxID_ANY );
+    dataview_right = new wxDataViewCtrl( m_splitter, wxID_ANY, wxDefaultPosition,
+                                         wxDefaultSize, style );
     dataview_right->AssociateModel( model );
 
     text_renderer = new wxDataViewTextRenderer( wxT("string"), wxDATAVIEW_CELL_EDITABLE );
@@ -439,19 +552,25 @@ MyFrame::MyFrame(wxFrame *frame, wxChar *title, int x, int y, int w, int h):
     dataview_right->AppendColumn( column );
     dataview_right->AppendTextColumn( wxT("first"), 0 );
     dataview_right->AppendTextColumn( wxT("second"), 1 );
-    wxDataViewToggleRenderer *toggle_renderer = new wxDataViewToggleRenderer( wxT("bool"), wxDATAVIEW_CELL_ACTIVATABLE );
+    wxDataViewToggleRenderer *toggle_renderer = 
+        new wxDataViewToggleRenderer( wxT("bool"), wxDATAVIEW_CELL_ACTIVATABLE );
     column = new wxDataViewColumn( wxT("bool"), toggle_renderer, 3, 30 );
     dataview_right->AppendColumn( column );
 
     dataview_right->AppendDateColumn( wxT("date"), 6 );
 
-    // layout dataview controls.
+    // layout dataview controls
+    if (old1)
+    {
+        m_splitter->ReplaceWindow(old1, dataview_left);
+        delete old1;
+    }
 
-    wxBoxSizer *sizer = new wxBoxSizer( wxHORIZONTAL );
-    sizer->Add( dataview_left, 3, wxGROW );
-    sizer->Add(10,10);
-    sizer->Add( dataview_right, 2, wxGROW );
-    panel->SetSizer( sizer );
+    if (old2)
+    {
+        m_splitter->ReplaceWindow(old2, dataview_right);
+        delete old2;
+    }
 }
 
 void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event) )
@@ -461,12 +580,84 @@ void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event) )
 
 void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event) )
 {
-    wxMessageDialog dialog(this, _T("This demonstrates the dataview control handling"),
-        _T("About DataView"), wxOK);
+    wxAboutDialogInfo info;
+    info.SetName(_("DataView sample"));
+    info.SetDescription(_("This sample demonstrates the dataview control handling"));
+    info.SetCopyright(_T("(C) 2007 Robert Roebling"));
 
-    dialog.ShowModal();
+    wxAboutBox(info);
+}
+
+void MyFrame::OnNewSortingFrame(wxCommandEvent& WXUNUSED(event) )
+{
+    MySortingFrame *frame2 = 
+        new MySortingFrame(NULL, wxT("wxDataViewCtrl sorting test"), 10, 150, 600, 500);
+    frame2->Show(true);
+}
+
+void MyFrame::OnSingleSelMode(wxCommandEvent& event)
+{
+    CreateControls();
+}
+
+void MyFrame::OnMultipleSelMode(wxCommandEvent& event)
+{
+    CreateControls();
+}
+
+void MyFrame::OnResizeableColumn(wxCommandEvent& event)
+{
+    CreateControls();
+}
+
+void MyFrame::OnSortableColumn(wxCommandEvent& event)
+{
+    CreateControls();
+}
+
+void MyFrame::OnHideColumn(wxCommandEvent& event)
+{
+    CreateControls();
 }
 
+void MyFrame::OnChooseAlign(wxCommandEvent& event)
+{
+    const wxString choices[] =
+    {
+        wxT("Left"),
+        wxT("Center horizontally"),
+        wxT("Right"),
+        wxT("Top"),
+        wxT("Center vertically"),
+        wxT("Bottom"),
+        wxT("Center")
+    };
+
+    wxAlignment flags[] =
+    {
+        wxALIGN_LEFT,
+        wxALIGN_CENTER_HORIZONTAL,
+        wxALIGN_RIGHT,
+        wxALIGN_TOP,
+        wxALIGN_CENTER_VERTICAL,
+        wxALIGN_BOTTOM,
+        wxALIGN_CENTER
+    };
+
+    int choice = wxGetSingleChoiceIndex(
+        wxT("Select the alignment for the cells of the wxDataViewCtrl:"),
+        wxT("Alignment"),
+        WXSIZEOF(choices), choices,
+        this);
+
+    if (choice == wxNOT_FOUND)
+        return;
+
+    m_align = flags[choice];
+    CreateControls();
+}
+
+
 // -------------------------------------
 // MySortingFrame
 // -------------------------------------
@@ -491,43 +682,39 @@ MySortingFrame::MySortingFrame(wxFrame *frame, wxChar *title, int x, int y, int
     m_logOld = NULL;
     
     SetIcon(wxICON(sample));
-
-    wxMenu *file_menu = new wxMenu;
-
-    file_menu->Append(DYNAMIC_ABOUT, _T("&About"));
-    file_menu->Append(DYNAMIC_QUIT, _T("E&xit"));
-    wxMenuBar *menu_bar = new wxMenuBar;
-    menu_bar->Append(file_menu, _T("&File"));
-    SetMenuBar(menu_bar);
-
-    // You used to have to do some casting for param 4, but now there are type-safe handlers
-    Connect( DYNAMIC_QUIT,  wxID_ANY,
-                    wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MySortingFrame::OnQuit) );
-    Connect( DYNAMIC_ABOUT, wxID_ANY,
-                    wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MySortingFrame::OnAbout) );
-
     CreateStatusBar();
 
+    wxPanel *main = new wxPanel(this);
 
     // Left wxDataViewCtrl
-    dataview_left = new wxDataViewCtrl( this, ID_UNSORTED, wxDefaultPosition, wxDefaultSize, wxDV_MULTIPLE );
+    dataview_left = new wxDataViewCtrl( main, ID_UNSORTED, wxDefaultPosition, 
+                                        wxDefaultSize, wxDV_MULTIPLE );
 
     m_unsorted_model = new MyUnsortedTextModel;
     dataview_left->AssociateModel( m_unsorted_model );
-    wxDataViewTextRenderer *text_renderer = new wxDataViewTextRenderer( wxT("string"), wxDATAVIEW_CELL_EDITABLE );
+    m_unsorted_model->DecRef(); // don't leak memory
+
+    wxDataViewTextRenderer *text_renderer = 
+        new wxDataViewTextRenderer( wxT("string"), wxDATAVIEW_CELL_EDITABLE );
     wxDataViewColumn *column = new wxDataViewColumn( wxT("editable"), text_renderer, 0 );
     dataview_left->AppendColumn( column );
     dataview_left->AppendTextColumn( wxT("second"), 1 );
-    dataview_left->AppendColumn( new wxDataViewColumn( wxBitmap(null_xpm), new wxDataViewBitmapRenderer, 2, 25 ) );
-    dataview_left->AppendColumn( new wxDataViewColumn( wxT("icon"), new wxDataViewBitmapRenderer, 3, 25 ) );
+    dataview_left->AppendColumn( new wxDataViewColumn( wxBitmap(null_xpm), 
+                                 new wxDataViewBitmapRenderer, 2, 25 ) );
+    dataview_left->AppendColumn( new wxDataViewColumn( wxT("icon"), 
+                                 new wxDataViewBitmapRenderer, 3, 25 ) );
 
     // Right wxDataViewCtrl using the sorting model
-    dataview_right = new wxDataViewCtrl( this, ID_SORTED );
+    dataview_right = new wxDataViewCtrl( main, ID_SORTED );
     
     m_sorted_model = new wxDataViewSortedListModel( m_unsorted_model );
     dataview_right->AssociateModel( m_sorted_model );
+    m_sorted_model->DecRef(); // don't leak memory
+
     text_renderer = new wxDataViewTextRenderer( wxT("string"), wxDATAVIEW_CELL_EDITABLE );
-    column = new wxDataViewColumn( wxT("editable"), text_renderer, 0, -1, wxDATAVIEW_COL_SORTABLE|wxDATAVIEW_COL_RESIZABLE );
+    column = new wxDataViewColumn( wxT("editable"), text_renderer, 0, -1, 
+                                   wxALIGN_CENTER,
+                                   wxDATAVIEW_COL_SORTABLE|wxDATAVIEW_COL_RESIZABLE );
     dataview_right->AppendColumn( column );
     
     dataview_right->AppendTextColumn( wxT("second"), 1 );
@@ -542,22 +729,22 @@ MySortingFrame::MySortingFrame(wxFrame *frame, wxChar *title, int x, int y, int
     wxBoxSizer *button_sizer = new wxBoxSizer( wxHORIZONTAL );
     button_sizer->Add( 10, 10, 1 );
     wxFlexGridSizer *left_sizer = new wxFlexGridSizer( 2 );
-    left_sizer->Add( new wxButton( this, ID_APPEND_ROW_LEFT, wxT("Append") ), 0, wxALL, 5 );
-    left_sizer->Add( new wxButton( this, ID_PREPEND_ROW_LEFT, wxT("Prepend") ), 0, wxALL, 5 );
-    left_sizer->Add( new wxButton( this, ID_INSERT_ROW_LEFT, wxT("Insert") ), 0, wxALL, 5 );
-    left_sizer->Add( new wxButton( this, ID_DELETE_ROW_LEFT, wxT("Delete second") ), 0, wxALL, 5 );
-    left_sizer->Add( new wxButton( this, ID_EDIT_ROW_LEFT, wxT("Edit") ), 0, wxALL, 5 );
+    left_sizer->Add( new wxButton( main, ID_APPEND_ROW_LEFT, wxT("Append") ), 0, wxALL, 5 );
+    left_sizer->Add( new wxButton( main, ID_PREPEND_ROW_LEFT, wxT("Prepend") ), 0, wxALL, 5 );
+    left_sizer->Add( new wxButton( main, ID_INSERT_ROW_LEFT, wxT("Insert") ), 0, wxALL, 5 );
+    left_sizer->Add( new wxButton( main, ID_DELETE_ROW_LEFT, wxT("Delete second") ), 0, wxALL, 5 );
+    left_sizer->Add( new wxButton( main, ID_EDIT_ROW_LEFT, wxT("Edit") ), 0, wxALL, 5 );
     left_sizer->Add( 5,5 );
-    left_sizer->Add( new wxButton( this, ID_SELECT, wxT("Select third") ), 0, wxALL, 5 );
-    left_sizer->Add( new wxButton( this, ID_UNSELECT_ALL, wxT("Unselect all") ), 0, wxALL, 5 );
+    left_sizer->Add( new wxButton( main, ID_SELECT, wxT("Select third") ), 0, wxALL, 5 );
+    left_sizer->Add( new wxButton( main, ID_UNSELECT_ALL, wxT("Unselect all") ), 0, wxALL, 5 );
     button_sizer->Add( left_sizer );
     button_sizer->Add( 10, 10, 2 );
     wxFlexGridSizer *right_sizer = new wxFlexGridSizer( 2 );
-    right_sizer->Add( new wxButton( this, ID_APPEND_ROW_RIGHT, wxT("Append") ), 0, wxALL, 5 );
-    right_sizer->Add( new wxButton( this, ID_PREPEND_ROW_RIGHT, wxT("Prepend") ), 0, wxALL, 5 );
-    right_sizer->Add( new wxButton( this, ID_INSERT_ROW_RIGHT, wxT("Insert") ), 0, wxALL, 5 );
-    right_sizer->Add( new wxButton( this, ID_DELETE_ROW_RIGHT, wxT("Delete second") ), 0, wxALL, 5 );
-    right_sizer->Add( new wxButton( this, ID_EDIT_ROW_RIGHT, wxT("Edit") ), 0, wxALL, 5 );
+    right_sizer->Add( new wxButton( main, ID_APPEND_ROW_RIGHT, wxT("Append") ), 0, wxALL, 5 );
+    right_sizer->Add( new wxButton( main, ID_PREPEND_ROW_RIGHT, wxT("Prepend") ), 0, wxALL, 5 );
+    right_sizer->Add( new wxButton( main, ID_INSERT_ROW_RIGHT, wxT("Insert") ), 0, wxALL, 5 );
+    right_sizer->Add( new wxButton( main, ID_DELETE_ROW_RIGHT, wxT("Delete second") ), 0, wxALL, 5 );
+    right_sizer->Add( new wxButton( main, ID_EDIT_ROW_RIGHT, wxT("Edit") ), 0, wxALL, 5 );
     button_sizer->Add( right_sizer );
     button_sizer->Add( 10, 10, 1 );
 
@@ -565,7 +752,7 @@ MySortingFrame::MySortingFrame(wxFrame *frame, wxChar *title, int x, int y, int
     main_sizer->Add( top_sizer, 1, wxGROW );
     main_sizer->Add( button_sizer, 0, wxGROW );
     
-    m_logWindow = new wxTextCtrl(this, wxID_ANY, wxEmptyString,
+    m_logWindow = new wxTextCtrl(main, wxID_ANY, wxEmptyString,
                                  wxDefaultPosition, wxDefaultSize,
                                  wxTE_MULTILINE | wxSUNKEN_BORDER);
     main_sizer->Add( 20,20 );
@@ -573,7 +760,7 @@ MySortingFrame::MySortingFrame(wxFrame *frame, wxChar *title, int x, int y, int
 
     m_logOld = wxLog::SetActiveTarget(new wxLogTextCtrl(m_logWindow));
 
-    SetSizer( main_sizer );
+    main->SetSizer( main_sizer );
 }
 
 MySortingFrame::~MySortingFrame()
@@ -625,7 +812,8 @@ void MySortingFrame::OnHeaderClickSorted(wxDataViewEvent &event)
 
 void MySortingFrame::OnHeaderClickUnsorted(wxDataViewEvent &event)
 {
-    wxLogMessage( wxT("OnHeaderClick from unsorted list, column %s"), event.GetDataViewColumn()->GetTitle().c_str() );
+    wxLogMessage( wxT("OnHeaderClick from unsorted list, column %s"), 
+                  event.GetDataViewColumn()->GetTitle().c_str() );
 }
 
 void MySortingFrame::OnQuit(wxCommandEvent& WXUNUSED(event) )
index 1094b1ebcadab777192d344449f3d85305d35dd4..8ebcfef112748d30489957e46114ed6d02a33ebd 100644 (file)
 
 const wxChar wxDataViewCtrlNameStr[] = wxT("dataviewCtrl");
 
-// ---------------------------------------------------------
-// wxDataViewModel
-// ---------------------------------------------------------
-
-IMPLEMENT_ABSTRACT_CLASS(wxDataViewModel, wxObject)
 
 // ---------------------------------------------------------
 // wxDataViewListModel
 // ---------------------------------------------------------
 
-IMPLEMENT_ABSTRACT_CLASS(wxDataViewListModel, wxDataViewModel)
-
 wxDataViewListModel::wxDataViewListModel()
 {
     m_viewingColumns.DeleteContents( true );
@@ -45,6 +38,13 @@ wxDataViewListModel::wxDataViewListModel()
 
 wxDataViewListModel::~wxDataViewListModel()
 {
+    wxList::compatibility_iterator node = m_notifiers.GetFirst();
+    while (node)
+    {
+        wxDataViewListModelNotifier* notifier = (wxDataViewListModelNotifier*) node->GetData();
+        notifier->Freed();
+        node = node->GetNext();
+    }
 }
 
 bool wxDataViewListModel::RowAppended()
@@ -242,6 +242,9 @@ public:
     virtual bool Cleared()
         { return m_model->ChildCleared(); }
 
+    virtual bool Freed()
+        { m_model->m_child = NULL; return wxDataViewListModelNotifier::Freed(); }
+
     wxDataViewSortedListModel *m_model;
 };
 
@@ -306,8 +309,6 @@ int LINKAGEMODE wxDataViewIntermediateCmp( unsigned int row1, unsigned int row2
 // wxDataViewSortedListModel
 // ---------------------------------------------------------
 
-IMPLEMENT_ABSTRACT_CLASS(wxDataViewSortedListModel, wxDataViewListModel)
-
 wxDataViewSortedListModel::wxDataViewSortedListModel( wxDataViewListModel *child ) :
   m_array( wxDataViewIntermediateCmp )
 {
@@ -323,6 +324,7 @@ wxDataViewSortedListModel::wxDataViewSortedListModel( wxDataViewListModel *child
 
 wxDataViewSortedListModel::~wxDataViewSortedListModel()
 {
+    if (m_child)
     m_child->RemoveNotifier( m_notifierOnChild );
 }
 
@@ -715,6 +717,7 @@ wxDataViewColumnBase::wxDataViewColumnBase(const wxString& title,
                                            wxDataViewRenderer *renderer,
                                            unsigned int model_column,
                                            int WXUNUSED(width),
+                                           wxAlignment WXUNUSED(align),
                                            int flags ) 
 {
     m_renderer = renderer;
@@ -729,6 +732,7 @@ wxDataViewColumnBase::wxDataViewColumnBase(const wxBitmap& bitmap,
                                            wxDataViewRenderer *renderer,
                                            unsigned int model_column,
                                            int WXUNUSED(width),
+                                           wxAlignment WXUNUSED(align),
                                            int flags ) 
 {
     m_renderer = renderer;
@@ -784,11 +788,27 @@ wxDataViewCtrlBase::wxDataViewCtrlBase()
 
 wxDataViewCtrlBase::~wxDataViewCtrlBase()
 {
+    // IMPORTANT: before calling DecRef() on our model (since it may 
+    //            result in a free() call), erase all columns (since
+    //            they hold a pointer to our model)
+    m_cols.Clear();
+
+    if (m_model)
+    {
+        m_model->DecRef();
+        m_model = NULL;
+    }
 }
 
 bool wxDataViewCtrlBase::AssociateModel( wxDataViewListModel *model )
 {
+    if ( m_model )
+        m_model->DecRef();   // discard old model, if any
+
+    // add our own reference to the new model:
     m_model = model;
+    if ( m_model )
+        m_model->IncRef(); 
 
     return true;
 }
@@ -799,73 +819,83 @@ wxDataViewListModel* wxDataViewCtrlBase::GetModel()
 }
 
 bool wxDataViewCtrlBase::AppendTextColumn( const wxString &label, unsigned int model_column,
-                            wxDataViewCellMode mode, int width )
+                            wxDataViewCellMode mode, int width, wxAlignment align, int flags )
 {
     return AppendColumn( new wxDataViewColumn( label, 
-        new wxDataViewTextRenderer( wxT("string"), mode ), model_column, width ) );
+        new wxDataViewTextRenderer( wxT("string"), mode ), model_column, 
+        width, align, flags ) );
 }
 
 bool wxDataViewCtrlBase::AppendToggleColumn( const wxString &label, unsigned int model_column,
-                            wxDataViewCellMode mode, int width )
+                            wxDataViewCellMode mode, int width, wxAlignment align, int flags )
 {
     return AppendColumn( new wxDataViewColumn( label, 
-        new wxDataViewToggleRenderer( wxT("bool"), mode ), model_column, width ) );
+        new wxDataViewToggleRenderer( wxT("bool"), mode ), model_column, 
+        width, align, flags ) );
 }
 
 bool wxDataViewCtrlBase::AppendProgressColumn( const wxString &label, unsigned int model_column,
-                            wxDataViewCellMode mode, int width )
+                            wxDataViewCellMode mode, int width, wxAlignment align, int flags )
 {
     return AppendColumn( new wxDataViewColumn( label, 
-        new wxDataViewProgressRenderer( wxEmptyString, wxT("long"), mode ), model_column, width ) );
+        new wxDataViewProgressRenderer( wxEmptyString, wxT("long"), mode ), model_column, 
+        width, align, flags ) );
 }
 
 bool wxDataViewCtrlBase::AppendDateColumn( const wxString &label, unsigned int model_column,
-                            wxDataViewCellMode mode, int width )
+                            wxDataViewCellMode mode, int width, wxAlignment align, int flags )
 {
     return AppendColumn( new wxDataViewColumn( label, 
-        new wxDataViewDateRenderer( wxT("datetime"), mode), model_column, width ) );
+        new wxDataViewDateRenderer( wxT("datetime"), mode), model_column, 
+        width, align, flags ) );
 }
 
 bool wxDataViewCtrlBase::AppendBitmapColumn( const wxString &label, unsigned int model_column,
-                            wxDataViewCellMode mode, int width )
+                            wxDataViewCellMode mode, int width, wxAlignment align, int flags )
 {
     return AppendColumn( new wxDataViewColumn( label, 
-        new wxDataViewBitmapRenderer( wxT("wxBitmap"), mode ), model_column, width ) );
+        new wxDataViewBitmapRenderer( wxT("wxBitmap"), mode ), model_column, 
+        width, align, flags ) );
 }
 
 bool wxDataViewCtrlBase::AppendTextColumn( const wxBitmap &label, unsigned int model_column,
-                            wxDataViewCellMode mode, int width )
+                            wxDataViewCellMode mode, int width, wxAlignment align, int flags )
 {
     return AppendColumn( new wxDataViewColumn( label, 
-        new wxDataViewTextRenderer( wxT("string"), mode ), model_column, width ) );
+        new wxDataViewTextRenderer( wxT("string"), mode ), model_column, 
+        width, align, flags ) );
 }
 
 bool wxDataViewCtrlBase::AppendToggleColumn( const wxBitmap &label, unsigned int model_column,
-                            wxDataViewCellMode mode, int width )
+                            wxDataViewCellMode mode, int width, wxAlignment align, int flags )
 {
     return AppendColumn( new wxDataViewColumn( label, 
-        new wxDataViewToggleRenderer( wxT("bool"), mode ), model_column, width ) );
+        new wxDataViewToggleRenderer( wxT("bool"), mode ), model_column, 
+        width, align, flags ) );
 }
 
 bool wxDataViewCtrlBase::AppendProgressColumn( const wxBitmap &label, unsigned int model_column,
-                            wxDataViewCellMode mode, int width )
+                            wxDataViewCellMode mode, int width, wxAlignment align, int flags )
 {
     return AppendColumn( new wxDataViewColumn( label, 
-        new wxDataViewProgressRenderer( wxEmptyString, wxT("long"), mode ), model_column, width ) );
+        new wxDataViewProgressRenderer( wxEmptyString, wxT("long"), mode ), model_column, 
+        width, align, flags ) );
 }
 
 bool wxDataViewCtrlBase::AppendDateColumn( const wxBitmap &label, unsigned int model_column,
-                            wxDataViewCellMode mode, int width )
+                            wxDataViewCellMode mode, int width, wxAlignment align, int flags )
 {
     return AppendColumn( new wxDataViewColumn( label, 
-        new wxDataViewDateRenderer( wxT("datetime"), mode ), model_column, width ) );
+        new wxDataViewDateRenderer( wxT("datetime"), mode ), model_column,
+        width, align, flags ) );
 }
 
 bool wxDataViewCtrlBase::AppendBitmapColumn( const wxBitmap &label, unsigned int model_column,
-                            wxDataViewCellMode mode, int width )
+                            wxDataViewCellMode mode, int width, wxAlignment align, int flags )
 {
     return AppendColumn( new wxDataViewColumn( label, 
-        new wxDataViewBitmapRenderer( wxT("wxBitmap"), mode ), model_column, width ) );
+        new wxDataViewBitmapRenderer( wxT("wxBitmap"), mode ), model_column, 
+        width, align, flags ) );
 }
 
 bool wxDataViewCtrlBase::AppendColumn( wxDataViewColumn *col )
index f1bcc09c3cf2a1ba0e7866de5a3cc2a2747a6bf1..c6996a685f6508c7bf4246f6bcbe820a0bc97e33 100644 (file)
@@ -2,6 +2,7 @@
 // Name:        src/generic/datavgen.cpp
 // Purpose:     wxDataViewCtrl generic implementation
 // Author:      Robert Roebling
+// Modified by: Francesco Montorsi, Guru Kathiresan, Otto Wyss
 // Id:          $Id$
 // Copyright:   (c) 1998 Robert Roebling
 // Licence:     wxWindows licence
@@ -22,7 +23,9 @@
 
 #ifndef WX_PRECOMP
     #ifdef __WXMSW__
+        #include "wx/msw/private.h"
         #include "wx/msw/wrapwin.h"
+        #include "wx/msw/wrapcctl.h" // include <commctrl.h> "properly"
     #endif
     #include "wx/sizer.h"
     #include "wx/log.h"
@@ -49,32 +52,157 @@ class wxDataViewCtrl;
 // wxDataViewHeaderWindow
 //-----------------------------------------------------------------------------
 
-class wxDataViewHeaderWindow: public wxWindow
+#define USE_NATIVE_HEADER_WINDOW    1
+
+class wxDataViewHeaderWindowBase : public wxControl
+{
+public:
+    wxDataViewHeaderWindowBase()
+        { m_owner = NULL; }
+
+    bool Create(wxDataViewCtrl *parent, wxWindowID id,
+                const wxPoint &pos, const wxSize &size, 
+                const wxString &name)
+    {
+        return wxWindow::Create(parent, id, pos, size, wxNO_BORDER, name);
+    }
+
+    void SetOwner( wxDataViewCtrl* owner ) { m_owner = owner; }
+    wxDataViewCtrl *GetOwner() { return m_owner; }
+
+    // called on column addition/removal
+    virtual void UpdateDisplay() { /* by default, do nothing */ }
+
+    // updates the n-th column's width
+    virtual void SetColumnWidth(unsigned int n, int width);
+
+    // returns the n-th column
+    wxDataViewColumn *GetColumn(unsigned int n)
+    {
+        wxASSERT(m_owner);
+        wxDataViewColumn *ret = m_owner->GetColumn(n); 
+        wxASSERT(ret);
+
+        return ret; 
+    }
+
+protected:
+    wxDataViewCtrl      *m_owner;
+
+    // sends an event generated from the n-th wxDataViewColumn
+    void SendEvent(wxEventType type, unsigned int n);
+};
+
+// on wxMSW the header window (only that part however) can be made native!
+#if defined(__WXMSW__) && USE_NATIVE_HEADER_WINDOW
+
+#define wxDataViewHeaderWindowMSW   wxDataViewHeaderWindow
+
+class wxDataViewHeaderWindowMSW : public wxDataViewHeaderWindowBase
 {
 public:
-    wxDataViewHeaderWindow( wxDataViewCtrl *parent,
+
+    wxDataViewHeaderWindowMSW( wxDataViewCtrl *parent,
                             wxWindowID id,
                             const wxPoint &pos = wxDefaultPosition,
                             const wxSize &size = wxDefaultSize,
-                            const wxString &name = wxT("wxdataviewctrlheaderwindow") );
-    virtual ~wxDataViewHeaderWindow();
+                                const wxString &name = wxT("wxdataviewctrlheaderwindow") )
+    { 
+        Create(parent, id, pos, size, name);
+    }
 
-    void SetOwner( wxDataViewCtrl* owner ) { m_owner = owner; }
-    wxDataViewCtrl *GetOwner() { return m_owner; }
+    bool Create(wxDataViewCtrl *parent, wxWindowID id,
+                const wxPoint &pos, const wxSize &size, 
+                const wxString &name);
+
+    ~wxDataViewHeaderWindowMSW();
+
+    // called on column addition/removal
+    virtual void UpdateDisplay();
+
+    // called when the main window gets scrolled
+    virtual void ScrollWindow(int dx, int dy, const wxRect *rect = NULL);
+
+protected:
+    virtual bool MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result);
+    
+private:
+    DECLARE_DYNAMIC_CLASS(wxDataViewHeaderWindowMSW)
+};
+
+#else       // !defined(__WXMSW__)
+
+#define HEADER_WINDOW_HEIGHT            25
+#define wxGenericDataViewHeaderWindow   wxDataViewHeaderWindow
+
+class wxGenericDataViewHeaderWindow : public wxDataViewHeaderWindowBase
+{
+public:
+    wxGenericDataViewHeaderWindow( wxDataViewCtrl *parent,
+                                    wxWindowID id,
+                                    const wxPoint &pos = wxDefaultPosition,
+                                    const wxSize &size = wxDefaultSize,
+                                    const wxString &name = wxT("wxdataviewctrlheaderwindow") )
+    { 
+        Init();
+        Create(parent, id, pos, size, name);
+    }
+
+    bool Create(wxDataViewCtrl *parent, wxWindowID id,
+                const wxPoint &pos, const wxSize &size, 
+                const wxString &name);
+
+    ~wxGenericDataViewHeaderWindow()
+    {
+        delete m_resizeCursor;
+    }
+
+    // event handlers:
 
     void OnPaint( wxPaintEvent &event );
     void OnMouse( wxMouseEvent &event );
     void OnSetFocus( wxFocusEvent &event );
 
-private:
-    wxDataViewCtrl      *m_owner;
+
+protected:
+
+    // vars used for column resizing:
+
     wxCursor            *m_resizeCursor;
+    const wxCursor      *m_currentCursor;
+    bool                 m_isDragging;
+
+    bool                 m_dirty;     // needs refresh?
+    int                  m_column;    // index of the column being resized
+    int                  m_currentX;  // divider line position in logical (unscrolled) coords
+    int                  m_minX;      // minimal position beyond which the divider line 
+                                      // can't be dragged in logical coords
+
+    // internal utilities:
+
+    void Init()
+    {
+        m_currentCursor = (wxCursor *) NULL;
+        m_resizeCursor = new wxCursor( wxCURSOR_SIZEWE );
+
+        m_isDragging = false;
+        m_dirty = false;
+
+        m_column = wxNOT_FOUND;
+        m_currentX = 0;
+        m_minX = 0;
+    }
+
+    void DrawCurrent();
+    void AdjustDC(wxDC& dc);
 
 private:
-    DECLARE_DYNAMIC_CLASS(wxDataViewHeaderWindow)
+    DECLARE_DYNAMIC_CLASS(wxGenericDataViewHeaderWindow)
     DECLARE_EVENT_TABLE()
 };
 
+#endif      // defined(__WXMSW__)
+
 //-----------------------------------------------------------------------------
 // wxDataViewRenameTimer
 //-----------------------------------------------------------------------------
@@ -132,7 +260,8 @@ private:
 // wxDataViewMainWindow
 //-----------------------------------------------------------------------------
 
-WX_DEFINE_SORTED_USER_EXPORTED_ARRAY_SIZE_T(unsigned int, wxDataViewSelection, WXDLLIMPEXP_ADV);
+WX_DEFINE_SORTED_USER_EXPORTED_ARRAY_SIZE_T(unsigned int, wxDataViewSelection, 
+                                            WXDLLIMPEXP_ADV);
 
 class wxDataViewMainWindow: public wxWindow
 {
@@ -185,6 +314,7 @@ public:
     unsigned int GetLastVisibleRow();
     unsigned int GetRowCount();
 
+    void Select( const wxArrayInt& aSelections );
     void SelectAllRows( bool on );
     void SelectRow( unsigned int row, bool on );
     void SelectRows( unsigned int from, unsigned int to, bool on );
@@ -259,7 +389,8 @@ public:
 
 IMPLEMENT_ABSTRACT_CLASS(wxDataViewRenderer, wxDataViewRendererBase)
 
-wxDataViewRenderer::wxDataViewRenderer( const wxString &varianttype, wxDataViewCellMode mode ) :
+wxDataViewRenderer::wxDataViewRenderer( const wxString &varianttype, 
+                                        wxDataViewCellMode mode ) :
     wxDataViewRendererBase( varianttype, mode )
 {
     m_dc = NULL;
@@ -303,7 +434,8 @@ wxDataViewCustomRenderer::wxDataViewCustomRenderer( const wxString &varianttype,
 
 IMPLEMENT_CLASS(wxDataViewTextRenderer, wxDataViewCustomRenderer)
 
-wxDataViewTextRenderer::wxDataViewTextRenderer( const wxString &varianttype, wxDataViewCellMode mode ) :
+wxDataViewTextRenderer::wxDataViewTextRenderer( const wxString &varianttype, 
+                                                wxDataViewCellMode mode ) :
     wxDataViewCustomRenderer( varianttype, mode )
 {
 }
@@ -320,15 +452,38 @@ bool wxDataViewTextRenderer::GetValue( wxVariant& WXUNUSED(value) )
     return false;
 }
 
-bool wxDataViewTextRenderer::Render( wxRect cell, wxDC *dc, int WXUNUSED(state) )
+bool wxDataViewTextRenderer::Render( wxRect cell, wxDC *dc, int state )
 {
+    wxDataViewCtrl *view = GetOwner()->GetOwner();
+    wxColour col = (state & wxDATAVIEW_CELL_SELECTED) ?
+                        wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT) :
+                        view->GetForegroundColour();
+
+    dc->SetTextForeground(col);
+
+    // TODO: it would be much more efficient to create a clipping
+    //       region for the entire column being rendered (in the OnPaint
+    //       of wxDataViewMainWindow) instead of a single clip region for
+    //       each cell. However it would mean that each renderer should
+    //       respect the given wxRect's top & bottom coords, eventually
+    //       violating only the left & right coords - however the user can
+    //       make its own renderer and thus we cannot be sure of that.
+    dc->SetClippingRegion(cell);
     dc->DrawText( m_text, cell.x, cell.y );
+    dc->DestroyClippingRegion();
 
     return true;
 }
 
 wxSize wxDataViewTextRenderer::GetSize()
 {
+    wxDataViewCtrl *view = GetOwner()->GetOwner();
+    if (!m_text.empty())
+    {
+        int x,y;
+        view->GetTextExtent( m_text, &x, &y );
+        return wxSize( x, y );
+    }
     return wxSize(80,20);
 }
 
@@ -338,7 +493,8 @@ wxSize wxDataViewTextRenderer::GetSize()
 
 IMPLEMENT_CLASS(wxDataViewBitmapRenderer, wxDataViewCustomRenderer)
 
-wxDataViewBitmapRenderer::wxDataViewBitmapRenderer( const wxString &varianttype, wxDataViewCellMode mode ) :
+wxDataViewBitmapRenderer::wxDataViewBitmapRenderer( const wxString &varianttype, 
+                                                    wxDataViewCellMode mode ) :
     wxDataViewCustomRenderer( varianttype, mode )
 {
 }
@@ -428,7 +584,9 @@ bool wxDataViewToggleRenderer::Render( wxRect cell, wxDC *dc, int WXUNUSED(state
     return true;
 }
 
-bool wxDataViewToggleRenderer::Activate( wxRect WXUNUSED(cell), wxDataViewListModel *model, unsigned int col, unsigned int row )
+bool wxDataViewToggleRenderer::Activate( wxRect WXUNUSED(cell), 
+                                         wxDataViewListModel *model, 
+                                         unsigned int col, unsigned int row )
 {
     bool value = !m_toggle;
     wxVariant variant = value;
@@ -580,7 +738,8 @@ wxSize wxDataViewDateRenderer::GetSize()
     return wxSize(x,y+d);
 }
 
-bool wxDataViewDateRenderer::Activate( wxRect WXUNUSED(cell), wxDataViewListModel *model, unsigned int col, unsigned int row )
+bool wxDataViewDateRenderer::Activate( wxRect WXUNUSED(cell), wxDataViewListModel *model, 
+                                       unsigned int col, unsigned int row )
 {
     wxVariant variant;
     model->GetValue( variant, col, row );
@@ -605,27 +764,28 @@ bool wxDataViewDateRenderer::Activate( wxRect WXUNUSED(cell), wxDataViewListMode
 
 IMPLEMENT_ABSTRACT_CLASS(wxDataViewColumn, wxDataViewColumnBase)
 
-wxDataViewColumn::wxDataViewColumn( const wxString &title, wxDataViewRenderer *cell, unsigned int model_column,
-        int width, int flags ) :
-    wxDataViewColumnBase( title, cell, model_column, width, flags )
+wxDataViewColumn::wxDataViewColumn( const wxString &title, wxDataViewRenderer *cell, 
+                                    unsigned int model_column,
+                                    int width, wxAlignment align, int flags ) :
+    wxDataViewColumnBase( title, cell, model_column, width, align, flags )
 {
-    m_width = width;
-    if (m_width < 0)
-        m_width = 80;
+    m_align = align;
+    Init(width < 0 ? 80 : width);
 }
 
-wxDataViewColumn::wxDataViewColumn( const wxBitmap &bitmap, wxDataViewRenderer *cell, unsigned int model_column,
-        int width, int flags ) :
-    wxDataViewColumnBase( bitmap, cell, model_column, width, flags )
+wxDataViewColumn::wxDataViewColumn( const wxBitmap &bitmap, wxDataViewRenderer *cell, 
+                                    unsigned int model_column,
+                                    int width, wxAlignment align, int flags ) :
+    wxDataViewColumnBase( bitmap, cell, model_column, width, align, flags )
 {
-    m_width = width;
-    if (m_width < 0)
-        m_width = 30;
+    m_align = align;
+    Init(width < 0 ? 30 : width);
 }
 
-void wxDataViewColumn::SetAlignment( wxAlignment WXUNUSED(align) )
+void wxDataViewColumn::Init(int width)
 {
-    // TODO
+    m_width = width;
+    m_fixedWidth = -1;
 }
 
 void wxDataViewColumn::SetSortable( bool WXUNUSED(sortable) )
@@ -633,18 +793,12 @@ void wxDataViewColumn::SetSortable( bool WXUNUSED(sortable) )
     // TODO
 }
 
-bool wxDataViewColumn::GetSortable()
-{
-    // TODO
-    return false;
-}
-
 void wxDataViewColumn::SetSortOrder( bool WXUNUSED(ascending) )
 {
     // TODO
 }
 
-bool wxDataViewColumn::IsSortOrderAscending()
+bool wxDataViewColumn::IsSortOrderAscending() const
 {
     // TODO
     return true;
@@ -667,30 +821,272 @@ void wxDataViewColumn::SetBitmap( const wxBitmap &bitmap )
 
 }
 
-int wxDataViewColumn::GetWidth()
+int wxDataViewColumn::GetWidth() const
 {
     return m_width;
 }
 
 //-----------------------------------------------------------------------------
-// wxDataViewHeaderWindow
+// wxDataViewHeaderWindowBase
 //-----------------------------------------------------------------------------
 
-IMPLEMENT_ABSTRACT_CLASS(wxDataViewHeaderWindow, wxWindow)
+void wxDataViewHeaderWindowBase::SetColumnWidth(unsigned int n, int width)
+{
+    GetColumn(n)->m_width = width;
+    m_owner->m_clientArea->RecalculateDisplay();
+}
+
+void wxDataViewHeaderWindowBase::SendEvent(wxEventType type, unsigned int n)
+{
+    wxWindow *parent = GetParent();
+    wxDataViewEvent le(type, parent->GetId());
+
+    le.SetEventObject(parent);
+    le.SetColumn(n);
+    le.SetDataViewColumn(GetColumn(n));
+    le.SetModel(GetOwner()->GetModel());
+
+    // for events created by wxDataViewHeaderWindow the
+    // row / value fields are not valid
+
+    parent->GetEventHandler()->ProcessEvent(le);
+}
+
+#if defined(__WXMSW__) && USE_NATIVE_HEADER_WINDOW
+
+// implemented in msw/window.cpp:
+void wxAssociateWinWithHandle(HWND hWnd, wxWindowMSW *win);
+void wxRemoveHandleAssociation(wxWindowMSW *win);
+
+// implemented in msw/listctrl.cpp:
+unsigned int wxMSWGetColumnClicked(NMHDR *nmhdr, POINT *ptClick);
+
+IMPLEMENT_ABSTRACT_CLASS(wxDataViewHeaderWindowMSW, wxWindow);
+
+bool wxDataViewHeaderWindowMSW::Create( wxDataViewCtrl *parent, wxWindowID id,
+                                        const wxPoint &pos, const wxSize &size, 
+                                        const wxString &name )
+{
+    m_owner = parent;
+
+    if ( !CreateControl(parent, id, pos, size, 0, wxDefaultValidator, name) )
+        return false;
+
+    int x = pos.x == wxDefaultCoord ? 0 : pos.x,
+        y = pos.y == wxDefaultCoord ? 0 : pos.y,
+        w = size.x == wxDefaultCoord ? 1 : size.x,
+        h = size.y == wxDefaultCoord ? 22 : size.y;
+
+    // create the native WC_HEADER window:
+    WXHWND hwndParent = (HWND)parent->GetHandle();
+    WXDWORD msStyle = WS_CHILD | HDS_BUTTONS | HDS_HORZ | HDS_HOTTRACK | HDS_FULLDRAG;
+    m_hWnd = CreateWindowEx(0, 
+                            WC_HEADER, 
+                            (LPCTSTR) NULL, 
+                            msStyle,
+                            x, y, w, h,
+                            (HWND)hwndParent, 
+                            (HMENU)-1, 
+                            wxGetInstance(), 
+                            (LPVOID) NULL);
+    if (m_hWnd == NULL) 
+    {
+        wxLogLastError(_T("CreateWindowEx"));
+        return false;
+    }
+
+    // we need to do the association to force wxWindow::HandleNotify
+    // to call wxDataViewHeaderWindow::MSWOnNotify
+    wxAssociateWinWithHandle((HWND)m_hWnd, this);
+
+
+       RECT rcParent; 
+       HDLAYOUT hdl; 
+       WINDOWPOS wp; 
+
+    // Retrieve the bounding rectangle of the parent window's 
+    // client area, and then request size and position values 
+    // from the header control. 
+    ::GetClientRect((HWND)hwndParent, &rcParent); 
+    
+    hdl.prc = &rcParent; 
+    hdl.pwpos = &wp; 
+    if (!SendMessage((HWND)m_hWnd, HDM_LAYOUT, 0, (LPARAM) &hdl)) 
+    {
+        wxLogLastError(_T("SendMessage"));
+        return false;
+    }
+    
+    // Set the size, position, and visibility of the header control. 
+    SetWindowPos((HWND)m_hWnd, 
+                 wp.hwndInsertAfter, 
+                 wp.x, wp.y, 
+                 wp.cx, wp.cy, 
+                 wp.flags | SWP_SHOWWINDOW);
+
+    // set our size hints: wxDataViewCtrl will put this wxWindow inside
+    // a wxBoxSizer and in order to avoid super-big header windows,
+    // we need to set our height as fixed
+    SetMinSize(wxSize(-1, wp.cy));
+    SetMaxSize(wxSize(-1, wp.cy));
+
+    // the following is required to get the default win's font for header windows
+    SetFont(GetFont());
+
+    return true;
+}
+
+wxDataViewHeaderWindowMSW::~wxDataViewHeaderWindow()
+{
+    wxRemoveHandleAssociation(this);
+}
+
+void wxDataViewHeaderWindowMSW::UpdateDisplay()
+{
+    // remove old columns
+    for (int i=0, max=Header_GetItemCount((HWND)m_hWnd); i < max; i++)
+        Header_DeleteItem((HWND)m_hWnd, 0);
+    
+    // add the updated array of columns to the header control
+    unsigned int cols = GetOwner()->GetNumberOfColumns();
+    for (unsigned int i = 0; i < cols; i++)
+    {
+        wxDataViewColumn *col = GetColumn( i );
+        if (col->IsHidden())
+            continue;      // don't add it!
+
+        HDITEM hdi;
+        hdi.mask = HDI_TEXT | HDI_FORMAT | HDI_WIDTH;
+        hdi.pszText = (WCHAR*) col->GetTitle().c_str();
+        hdi.cxy = col->GetWidth();
+        hdi.cchTextMax = sizeof(hdi.pszText)/sizeof(hdi.pszText[0]);
+        hdi.fmt = HDF_LEFT | HDF_STRING;
+        
+        SendMessage((HWND)m_hWnd, HDM_INSERTITEM, (WPARAM)i, (LPARAM)&hdi); 
+    }
+}
+
+bool wxDataViewHeaderWindowMSW::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
+{
+    NMHDR *nmhdr = (NMHDR *)lParam;
+
+    // is it a message from the header?
+    if ( nmhdr->hwndFrom != (HWND)m_hWnd )
+        return wxWindow::MSWOnNotify(idCtrl, lParam, result);
+
+    NMHEADER *nmHDR = (NMHEADER *)nmhdr;
+    switch ( nmhdr->code )
+    {
+        case HDN_BEGINTRACK:
+            // user has started to resize a column:
+            // do we need to veto it?
+            if (!GetColumn(nmHDR->iItem)->IsResizeable())
+            {
+                // veto it!
+                *result = TRUE;
+            }
+            break;
+
+        case HDN_BEGINDRAG:
+            // user has started to reorder a column
+            break;
+
+        case HDN_ITEMCHANGED:   // user is resizing a column
+        case HDN_ENDTRACK:      // user has finished resizing a column
+        case HDN_ENDDRAG:       // user has finished reordering a column
+
+            // update the width of the modified column:
+            if ((nmHDR->pitem->mask & HDI_WIDTH) != 0 &&
+                    nmHDR->pitem != NULL)
+                SetColumnWidth(nmHDR->iItem, nmHDR->pitem->cxy);
+            break;
+
+        case HDN_ITEMCLICK:
+            {
+                wxEventType evt = nmHDR->iButton == 0 ? 
+                        wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK :
+                        wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK;
+                SendEvent(evt, nmHDR->iItem);
+            }
+            break;
+
+        case NM_RCLICK:
+            {
+                // NOTE: for some reason (i.e. for a bug in Windows)
+                //       the HDN_ITEMCLICK notification is not sent on
+                //       right clicks, so we need to handle NM_RCLICK
+
+                POINT ptClick;
+                unsigned int column = 
+                    wxMSWGetColumnClicked(nmhdr, &ptClick);
+
+                if (column != wxNOT_FOUND)
+                    SendEvent(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK,
+                                column);
+            }
+            break;
+
+        case HDN_GETDISPINFOW:
+            // see wxListCtrl::MSWOnNotify for more info!
+            break;
+
+        case HDN_ITEMDBLCLICK:
+            {
+                unsigned int idx = nmHDR->iItem;
+                int w = GetOwner()->GetBestColumnWidth(idx);
+
+                // update the native control:
+                HDITEM hd;
+                ZeroMemory(&hd, sizeof(hd));
+                hd.mask = HDI_WIDTH;
+                hd.cxy = w;
+                Header_SetItem(GetHwnd(), idx, &hd);
+
+                // update the wxDataViewColumn class:
+                SetColumnWidth(idx, w);
+            }
+            break;
+
+        default:
+            return wxWindow::MSWOnNotify(idCtrl, lParam, result);
+    }
+
+    return true;
+}
+
+void wxDataViewHeaderWindowMSW::ScrollWindow(int WXUNUSED(dx), int WXUNUSED(dy), 
+                                             const wxRect *WXUNUSED(rect))
+{
+    wxSize ourSz = GetClientSize();
+    wxSize ownerSz = m_owner->GetClientSize();
+
+    // where should the (logical) origin of this window be placed?
+    int x1 = 0, y1 = 0;
+    m_owner->CalcUnscrolledPosition(0, 0, &x1, &y1);
 
-BEGIN_EVENT_TABLE(wxDataViewHeaderWindow,wxWindow)
-    EVT_PAINT         (wxDataViewHeaderWindow::OnPaint)
-    EVT_MOUSE_EVENTS  (wxDataViewHeaderWindow::OnMouse)
-    EVT_SET_FOCUS     (wxDataViewHeaderWindow::OnSetFocus)
+    // put this window on top of our parent and 
+    SetWindowPos((HWND)m_hWnd, HWND_TOP, -x1, y1, 
+                  ownerSz.GetWidth() + x1, ourSz.GetHeight(), 
+                  SWP_SHOWWINDOW);
+}
+
+#else       // !defined(__WXMSW__)
+
+IMPLEMENT_ABSTRACT_CLASS(wxGenericDataViewHeaderWindow, wxWindow)
+BEGIN_EVENT_TABLE(wxGenericDataViewHeaderWindow, wxWindow)
+    EVT_PAINT         (wxGenericDataViewHeaderWindow::OnPaint)
+    EVT_MOUSE_EVENTS  (wxGenericDataViewHeaderWindow::OnMouse)
+    EVT_SET_FOCUS     (wxGenericDataViewHeaderWindow::OnSetFocus)
 END_EVENT_TABLE()
 
-wxDataViewHeaderWindow::wxDataViewHeaderWindow( wxDataViewCtrl *parent, wxWindowID id,
-     const wxPoint &pos, const wxSize &size, const wxString &name ) :
-    wxWindow( parent, id, pos, size, 0, name )
+bool wxGenericDataViewHeaderWindow::Create(wxDataViewCtrl *parent, wxWindowID id,
+                                           const wxPoint &pos, const wxSize &size, 
+                                           const wxString &name ) 
 {
-    SetOwner( parent );
+    m_owner = parent;
 
-    m_resizeCursor = new wxCursor( wxCURSOR_SIZEWE );
+    if (!wxDataViewHeaderWindowBase::Create(parent, id, pos, size, name))
+        return false;
 
     wxVisualAttributes attr = wxPanel::GetClassDefaultAttributes();
     SetBackgroundStyle( wxBG_STYLE_CUSTOM );
@@ -698,14 +1094,17 @@ wxDataViewHeaderWindow::wxDataViewHeaderWindow( wxDataViewCtrl *parent, wxWindow
     SetOwnBackgroundColour( attr.colBg );
     if (!m_hasFont)
         SetOwnFont( attr.font );
-}
 
-wxDataViewHeaderWindow::~wxDataViewHeaderWindow()
-{
-    delete m_resizeCursor;
+    // set our size hints: wxDataViewCtrl will put this wxWindow inside
+    // a wxBoxSizer and in order to avoid super-big header windows,
+    // we need to set our height as fixed
+    SetMinSize(wxSize(-1, HEADER_WINDOW_HEIGHT));
+    SetMaxSize(wxSize(-1, HEADER_WINDOW_HEIGHT));
+
+    return true;
 }
 
-void wxDataViewHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
+void wxGenericDataViewHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
 {
     int w, h;
     GetClientSize( &w, &h );
@@ -731,10 +1130,11 @@ void wxDataViewHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
     int xpos = 0;
     for (i = 0; i < cols; i++)
     {
-        wxDataViewColumn *col = GetOwner()->GetColumn( i );
-        int width = col->GetWidth();
+        wxDataViewColumn *col = GetColumn( i );
+        if (col->IsHidden())
+            break;      // don't draw it!
 
-        int cw = width;
+        int cw = col->GetWidth();
         int ch = h;
 
         wxRendererNative::Get().DrawHeaderButton
@@ -748,20 +1148,173 @@ void wxDataViewHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
 
         dc.DrawText( col->GetTitle(), xpos+3, 3 );
 
-        xpos += width;
+        xpos += cw;
     }
 }
 
-void wxDataViewHeaderWindow::OnMouse( wxMouseEvent &WXUNUSED(event) )
+void wxGenericDataViewHeaderWindow::OnSetFocus( wxFocusEvent &event )
 {
+    GetParent()->SetFocus();
+    event.Skip();
 }
 
-void wxDataViewHeaderWindow::OnSetFocus( wxFocusEvent &event )
+void wxGenericDataViewHeaderWindow::OnMouse( wxMouseEvent &event )
 {
-    GetParent()->SetFocus();
-    event.Skip();
+    // we want to work with logical coords
+    int x;
+    m_owner->CalcUnscrolledPosition(event.GetX(), 0, &x, NULL);
+    int y = event.GetY();
+
+    if (m_isDragging)
+    {
+        // we don't draw the line beyond our window, 
+        // but we allow dragging it there
+        int w = 0;
+        GetClientSize( &w, NULL );
+        m_owner->CalcUnscrolledPosition(w, 0, &w, NULL);
+        w -= 6;
+
+        // erase the line if it was drawn
+        if (m_currentX < w) 
+            DrawCurrent();
+
+        if (event.ButtonUp()) 
+        {
+            m_isDragging = false;
+            if (HasCapture()) 
+                ReleaseMouse();
+
+            m_dirty = true;
+
+            SetColumnWidth(m_column, m_currentX - m_minX);
+
+            Refresh();
+            GetOwner()->Refresh();
+        }
+        else
+        {
+            m_currentX = wxMax(m_minX + 7, x);
+
+            // draw in the new location
+            if (m_currentX < w) DrawCurrent();
+        }
+
+    }
+    else     // not dragging
+    {
+        m_minX = 0;
+        m_column = wxNOT_FOUND;
+
+        bool hit_border = false;
+
+        // end of the current column
+        int xpos = 0;
+
+        // find the column where this event occured
+        int countCol = m_owner->GetNumberOfColumns();
+        for (int column = 0; column < countCol; column++) 
+        {
+            wxDataViewColumn *p = GetColumn(column);
+
+            if (p->IsHidden()) 
+                continue;   // skip if not shown
+
+            xpos += p->GetWidth();
+            m_column = column;
+            if ((abs(x-xpos) < 3) && (y < 22)) 
+            {
+                hit_border = true;
+                break;
+            }
+
+            if (x < xpos) 
+            {
+                // inside the column
+                break;
+            }
+
+            m_minX = xpos;
+        }
+
+        if (m_column == wxNOT_FOUND)
+            return;
+
+        bool resizeable = GetColumn(m_column)->IsResizeable();
+        if (event.LeftDClick() && resizeable)
+        {
+            SetColumnWidth(m_column, GetOwner()->GetBestColumnWidth(m_column));
+            Refresh();
+        }
+        else if (event.LeftDown() || event.RightUp())
+        {
+            if (hit_border && event.LeftDown() && resizeable) 
+            {
+                m_isDragging = true;
+                CaptureMouse();
+                m_currentX = x;
+                DrawCurrent();
+            }
+            else    // click on a column
+            {
+                wxEventType evt = event.LeftDown() ? 
+                        wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK :
+                        wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK;
+                SendEvent(evt, m_column);
+            }
+        }
+        else if (event.Moving())
+        {
+            if (hit_border && resizeable) 
+                m_currentCursor = m_resizeCursor;
+            else
+                m_currentCursor = wxSTANDARD_CURSOR;
+
+            SetCursor(*m_currentCursor);
+        }
+    }
+}
+
+void wxGenericDataViewHeaderWindow::DrawCurrent()
+{
+    int x1 = m_currentX;
+    int y1 = 0;
+    ClientToScreen (&x1, &y1);
+
+    int x2 = m_currentX-1;
+#ifdef __WXMSW__
+    ++x2; // but why ????
+#endif
+    int y2 = 0;
+    m_owner->GetClientSize( NULL, &y2 );
+    m_owner->ClientToScreen( &x2, &y2 );
+
+    wxScreenDC dc;
+    dc.SetLogicalFunction (wxINVERT);
+    //dc.SetPen (wxPen (*wxBLACK, 2, wxSOLID));
+    dc.SetPen(wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DLIGHT),1, wxSOLID));
+    dc.SetBrush (*wxTRANSPARENT_BRUSH);
+
+    AdjustDC(dc);
+    dc.DrawLine (x1, y1, x2, y2);
+    dc.SetLogicalFunction (wxCOPY);
+    dc.SetPen (wxNullPen);
+    dc.SetBrush (wxNullBrush);
+}
+
+void wxGenericDataViewHeaderWindow::AdjustDC(wxDC& dc)
+{
+    int xpix, x;
+
+    m_owner->GetScrollPixelsPerUnit( &xpix, NULL );
+    m_owner->GetViewStart( &x, NULL );
+
+    // shift the DC origin to match the position of the main window horizontal
+    // scrollbar: this allows us to always use logical coords
+    dc.SetDeviceOrigin( -x * xpix, 0 );
 }
 
+#endif      // defined(__WXMSW__)
+
 //-----------------------------------------------------------------------------
 // wxDataViewRenameTimer
 //-----------------------------------------------------------------------------
@@ -958,7 +1511,12 @@ wxDataViewMainWindow::wxDataViewMainWindow( wxDataViewCtrl *parent, wxWindowID i
     m_currentRow = 0;
 
     // TODO: we need to calculate this smartly
-    m_lineHeight = 20;
+    m_lineHeight = 
+#ifdef __WXMSW__
+        17;
+#else
+        20;
+#endif
 
     m_dragCount = 0;
     m_dragStart = wxPoint(0,0);
@@ -997,7 +1555,8 @@ void wxDataViewMainWindow::OnRenameTimer()
             break;
         xpos += c->GetWidth();
     }
-    wxRect labelRect( xpos, m_currentRow * m_lineHeight, m_currentCol->GetWidth(), m_lineHeight );
+    wxRect labelRect( xpos, m_currentRow * m_lineHeight, 
+                      m_currentCol->GetWidth(), m_lineHeight );
 
     wxClassInfo *textControlClass = CLASSINFO(wxTextCtrl);
 
@@ -1125,22 +1684,22 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
     wxDataViewListModel *model = GetOwner()->GetModel();
 
     unsigned int item_start = wxMax( 0, (update.y / m_lineHeight) );
-    unsigned int item_count = wxMin( (int)(((update.y + update.height) / m_lineHeight) - item_start + 1),
+    unsigned int item_count = 
+        wxMin( (int)(((update.y + update.height) / m_lineHeight) - item_start + 1),
                                (int)(model->GetNumberOfRows()-item_start) );
 
-
-
     unsigned int item;
     for (item = item_start; item < item_start+item_count; item++)
     {
-        if (m_selection.Index( item ) != wxNOT_FOUND)
+        bool selected = m_selection.Index( item ) != wxNOT_FOUND;
+        if (selected || item == m_currentRow)
         {
-            int flags = wxCONTROL_SELECTED;
+            int flags = selected ? wxCONTROL_SELECTED : 0;
             if (item == m_currentRow)
                 flags |= wxCONTROL_CURRENT;
             if (m_hasFocus)
                 flags |= wxCONTROL_FOCUSED;
-            wxRect rect( 0, item*m_lineHeight+1, GetEndOfLastCol(), m_lineHeight-2 );
+            wxRect rect( 0, item*m_lineHeight, GetEndOfLastCol(), m_lineHeight );
             wxRendererNative::Get().DrawItemSelectionRect
                                 (
                                     this,
@@ -1149,24 +1708,6 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
                                     flags
                                 );
         }
-        else
-        {
-            if (item == m_currentRow)
-            {
-                int flags = wxCONTROL_CURRENT;
-                if (m_hasFocus)
-                    flags |= wxCONTROL_FOCUSED;  // should have no effect
-                wxRect rect( 0, item*m_lineHeight+1, GetEndOfLastCol(), m_lineHeight-2 );
-                wxRendererNative::Get().DrawItemSelectionRect
-                                (
-                                    this,
-                                    dc,
-                                    rect,
-                                    flags
-                                );
-
-            }
-        }
     }
 
     wxRect cell_rect;
@@ -1180,28 +1721,50 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
         wxDataViewRenderer *cell = col->GetRenderer();
         cell_rect.width = col->GetWidth();
 
+        if (col->IsHidden())
+            continue;       // skipt it!
+
         for (item = item_start; item < item_start+item_count; item++)
         {
-            cell_rect.y = item*m_lineHeight;
+            // get the cell value and set it into the renderer
             wxVariant value;
             model->GetValue( value, col->GetModelColumn(), item );
             cell->SetValue( value );
-            wxSize size = cell->GetSize();
+
+            // update the y offset
+            cell_rect.y = item*m_lineHeight;
+
             // cannot be bigger than allocated space
+            wxSize size = cell->GetSize();
             size.x = wxMin( size.x, cell_rect.width );
             size.y = wxMin( size.y, cell_rect.height );
-            // TODO: check for left/right/centre alignment here
-            wxRect item_rect;
-            // for now: centre
+
+            wxRect item_rect(cell_rect.GetTopLeft(), size);
+
+            // horizontal alignment:
+            if (col->GetAlignment() & wxALIGN_CENTER_HORIZONTAL)
             item_rect.x = cell_rect.x + (cell_rect.width / 2) - (size.x / 2);
+            else if (col->GetAlignment() & wxALIGN_RIGHT)
+                item_rect.x = cell_rect.x + cell_rect.width - size.x;
+            //else: wxALIGN_LEFT is the default
+
+            // vertical alignment:
+            if (col->GetAlignment() & wxALIGN_CENTER_VERTICAL)
+                item_rect.y = cell_rect.y + (cell_rect.height / 2) - (size.y / 2);
+            else if (col->GetAlignment() & wxALIGN_BOTTOM)
+                item_rect.y = cell_rect.y + cell_rect.height - size.y;
+            //else: wxALIGN_TOP is the default
+
             item_rect.y = cell_rect.y + (cell_rect.height / 2) - (size.y / 2);
 
             item_rect.width = size.x;
             item_rect.height= size.y;
 
             int state = 0;
-            if (item == m_currentRow)
+            //if (item == m_currentRow)     -- seems wrong to me...
+            if (m_selection.Index(item) != wxNOT_FOUND)
                 state |= wxDATAVIEW_CELL_SELECTED;
+
             cell->Render( item_rect, &dc, state );
         }
 
@@ -1239,7 +1802,8 @@ unsigned int wxDataViewMainWindow::GetFirstVisibleRow()
 unsigned int wxDataViewMainWindow::GetLastVisibleRow()
 {
     wxSize client_size = GetClientSize();
-    m_owner->CalcUnscrolledPosition( client_size.x, client_size.y, &client_size.x, &client_size.y );
+    m_owner->CalcUnscrolledPosition( client_size.x, client_size.y, 
+                                     &client_size.x, &client_size.y );
 
     return wxMin( GetRowCount()-1, ((unsigned)client_size.y/m_lineHeight)+1 );
 }
@@ -1329,6 +1893,17 @@ void wxDataViewMainWindow::SelectRows( unsigned int from, unsigned int to, bool
     RefreshRows( from, to );
 }
 
+void wxDataViewMainWindow::Select( const wxArrayInt& aSelections )
+{
+    for (size_t i=0; i < aSelections.GetCount(); i++)
+    {
+        int n = aSelections[i];
+
+        m_selection.Add( n );
+        RefreshRow( n );
+    }
+}
+
 void wxDataViewMainWindow::ReverseRowSelection( unsigned int row )
 {
     if (m_selection.Index( row ) == wxNOT_FOUND)
@@ -1596,7 +2171,8 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event )
                 wxVariant value;
                 model->GetValue( value, col->GetModelColumn(), current );
                 cell->SetValue( value );
-                wxRect cell_rect( xpos, current * m_lineHeight, col->GetWidth(), m_lineHeight );
+                wxRect cell_rect( xpos, current * m_lineHeight, 
+                                  col->GetWidth(), m_lineHeight );
                 cell->Activate( cell_rect, model, col->GetModelColumn(), current );
             }
             return;
@@ -1731,7 +2307,8 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event )
         // Update selection here...
         m_currentCol = col;
 
-        m_lastOnSame = !forceClick && ((col == oldCurrentCol) && (current == oldCurrentRow)) && oldWasSelected;
+        m_lastOnSame = !forceClick && ((col == oldCurrentCol) && 
+                        (current == oldCurrentRow)) && oldWasSelected;
     }
 }
 
@@ -1780,7 +2357,8 @@ bool wxDataViewCtrl::Create(wxWindow *parent, wxWindowID id,
            const wxPoint& pos, const wxSize& size,
            long style, const wxValidator& validator )
 {
-    if (!wxControl::Create( parent, id, pos, size, style | wxScrolledWindowStyle|wxSUNKEN_BORDER, validator))
+    if (!wxControl::Create( parent, id, pos, size, 
+                            style | wxScrolledWindowStyle|wxSUNKEN_BORDER, validator))
         return false;
 
     Init();
@@ -1790,11 +2368,7 @@ bool wxDataViewCtrl::Create(wxWindow *parent, wxWindowID id,
 #endif
 
     m_clientArea = new wxDataViewMainWindow( this, wxID_ANY );
-#ifdef __WXMSW__
-    m_headerArea = new wxDataViewHeaderWindow( this, wxID_ANY, wxDefaultPosition, wxSize(wxDefaultCoord,22) );
-#else
-    m_headerArea = new wxDataViewHeaderWindow( this, wxID_ANY, wxDefaultPosition, wxSize(wxDefaultCoord,25) );
-#endif
+    m_headerArea = new wxDataViewHeaderWindow( this, wxID_ANY );
 
     SetTargetWindow( m_clientArea );
 
@@ -1859,23 +2433,24 @@ bool wxDataViewCtrl::AppendColumn( wxDataViewColumn *col )
         return false;
 
     m_clientArea->UpdateDisplay();
+    m_headerArea->UpdateDisplay();
 
     return true;
 }
 
-void wxDataViewCtrl::SetSelection( int WXUNUSED(row) )
+void wxDataViewCtrl::SetSelection( int row )
 {
-    // FIXME - TODO
+    m_clientArea->SelectRow(row, true);
 }
 
-void wxDataViewCtrl::SetSelectionRange( unsigned int WXUNUSED(from), unsigned int WXUNUSED(to) )
+void wxDataViewCtrl::SetSelectionRange( unsigned int from, unsigned int to )
 {
-    // FIXME - TODO
+    m_clientArea->SelectRows(from, to, true);
 }
 
-void wxDataViewCtrl::SetSelections( const wxArrayInt& WXUNUSED(aSelections) )
+void wxDataViewCtrl::SetSelections( const wxArrayInt& aSelections )
 {
-    // FIXME - TODO
+    m_clientArea->Select(aSelections);
 }
 
 void wxDataViewCtrl::Unselect( unsigned int WXUNUSED(row) )
index 02e84faae90e86284831ddce70b0d9fb5e25ee71..40b69f99e995a93bc4d6bcda478998771d4d1d4d 100644 (file)
@@ -726,6 +726,13 @@ public:
     virtual bool RowsReordered( unsigned int *new_order );
     virtual bool Cleared();
 
+    virtual bool Freed()
+{
+    m_wx_model = NULL;
+    m_gtk_store = NULL;
+    return wxDataViewListModelNotifier::Freed();
+}
+
     GtkWxListStore      *m_gtk_store;
     wxDataViewListModel *m_wx_model;
 };
@@ -1430,9 +1437,10 @@ static void wxGtkTreeCellDataFunc( GtkTreeViewColumn *column,
 
 IMPLEMENT_CLASS(wxDataViewColumn, wxDataViewColumnBase)
 
-wxDataViewColumn::wxDataViewColumn( const wxString &title, wxDataViewRenderer *cell, unsigned int model_column,
-    int width, int flags ) :
-    wxDataViewColumnBase( title, cell, model_column, width, flags )
+wxDataViewColumn::wxDataViewColumn( const wxString &title, wxDataViewRenderer *cell, 
+                                    unsigned int model_column, int width, 
+                                    wxAlignment align, int flags ) :
+    wxDataViewColumnBase( title, cell, model_column, width, align, flags )
 {
     m_isConnected = false;
 
@@ -1464,11 +1472,13 @@ wxDataViewColumn::wxDataViewColumn( const wxString &title, wxDataViewRenderer *c
     gtk_tree_view_column_set_cell_data_func( column, renderer,
         wxGtkTreeCellDataFunc, (gpointer) cell, NULL );
 
+    SetAlignment(align);
 }
 
-wxDataViewColumn::wxDataViewColumn( const wxBitmap &bitmap, wxDataViewRenderer *cell, unsigned int model_column,
-    int width, int flags ) :
-    wxDataViewColumnBase( bitmap, cell, model_column, width, flags )
+wxDataViewColumn::wxDataViewColumn( const wxBitmap &bitmap, wxDataViewRenderer *cell, 
+                                    unsigned int model_column, int width, 
+                                    wxAlignment align, int flags ) :
+    wxDataViewColumnBase( bitmap, cell, model_column, width, align, flags )
 {
     m_isConnected = false;
     
@@ -1497,6 +1507,8 @@ wxDataViewColumn::wxDataViewColumn( const wxBitmap &bitmap, wxDataViewRenderer *
 
     gtk_tree_view_column_set_cell_data_func( column, renderer,
         wxGtkTreeCellDataFunc, (gpointer) cell, NULL );
+
+    SetAlignment(align);
 }
 
 wxDataViewColumn::~wxDataViewColumn()
@@ -1605,7 +1617,7 @@ void wxDataViewColumn::SetSortable( bool sortable )
     gtk_tree_view_column_set_sort_indicator( column, sortable );
 }
 
-bool wxDataViewColumn::GetSortable()
+bool wxDataViewColumn::IsSortable() const
 {
     GtkTreeViewColumn *column = (GtkTreeViewColumn *)m_column;
     return gtk_tree_view_column_get_sort_indicator( column );
@@ -1621,14 +1633,14 @@ void wxDataViewColumn::SetSortOrder( bool ascending )
         gtk_tree_view_column_set_sort_order( column, GTK_SORT_DESCENDING );
 }
 
-bool wxDataViewColumn::IsSortOrderAscending()
+bool wxDataViewColumn::IsSortOrderAscending() const
 {
     GtkTreeViewColumn *column = (GtkTreeViewColumn *)m_column;
     
     return (gtk_tree_view_column_get_sort_order( column ) != GTK_SORT_DESCENDING);
 }
 
-int wxDataViewColumn::GetWidth()
+int wxDataViewColumn::GetWidth() const
 {
     return gtk_tree_view_column_get_width( (GtkTreeViewColumn *)m_column );
 }
@@ -1638,7 +1650,7 @@ void wxDataViewColumn::SetFixedWidth( int width )
     gtk_tree_view_column_set_fixed_width( (GtkTreeViewColumn *)m_column, width );
 }
 
-int wxDataViewColumn::GetFixedWidth()
+int wxDataViewColumn::GetFixedWidth() const
 {
     return gtk_tree_view_column_get_fixed_width( (GtkTreeViewColumn *)m_column );
 }
@@ -1680,6 +1692,10 @@ wxDataViewCtrl::~wxDataViewCtrl()
 {
     if (m_notifier)
         GetModel()->RemoveNotifier( m_notifier );
+
+    // remove the model from the GtkTreeView before it gets destroyed by the
+    // wxDataViewCtrlBase's dtor
+    gtk_tree_view_set_model( GTK_TREE_VIEW(m_treeview), NULL );
 }
 
 void wxDataViewCtrl::Init()