]> git.saurik.com Git - wxWidgets.git/blobdiff - src/generic/datavgen.cpp
Merge r53510 from 2.8 branch
[wxWidgets.git] / src / generic / datavgen.cpp
index 12420c5dde5ac5aa3a0721014e3ef85784a93f84..53cde9cdc6cfa8ba9630934de5687e160e6f122d 100644 (file)
@@ -44,6 +44,7 @@
 #include "wx/icon.h"
 #include "wx/list.h"
 #include "wx/listimpl.cpp"
+#include "wx/imaglist.h"
 
 //-----------------------------------------------------------------------------
 // classes
@@ -63,7 +64,10 @@ static const int EXPANDER_MARGIN = 4;
 // wxDataViewHeaderWindow
 //-----------------------------------------------------------------------------
 
-#define USE_NATIVE_HEADER_WINDOW    !defined(__WXUNIVERSAL__)
+// on wxMSW the header window (only that part however) can be made native!
+#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
+    #define USE_NATIVE_HEADER_WINDOW
+#endif
 
 //Below is the compare stuff
 //For the generic implements, both the leaf nodes and the nodes are sorted for fast search when needed
@@ -109,8 +113,7 @@ protected:
     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
+#ifdef USE_NATIVE_HEADER_WINDOW
 
 #define COLUMN_WIDTH_OFFSET         2
 #define wxDataViewHeaderWindowMSW   wxDataViewHeaderWindow
@@ -157,9 +160,10 @@ protected:
     wxDataViewColumn *GetColumnFromHeader(NMHEADER *nmHDR)
         { return GetColumn(GetColumnIdxFromHeader(nmHDR)); }
 
-    int   m_scrollOffsetX;
-    int   m_buttonHeight;
-    bool  m_delayedUpdate;
+    int          m_scrollOffsetX;
+    int          m_buttonHeight;
+    bool         m_delayedUpdate;
+    wxImageList *m_imageList;
 
 private:
     DECLARE_DYNAMIC_CLASS(wxDataViewHeaderWindowMSW)
@@ -639,6 +643,29 @@ wxDC *wxDataViewRenderer::GetDC()
     return m_dc;
 }
 
+void wxDataViewRenderer::SetAlignment( int align )
+{ 
+    m_align=align;
+}
+
+int wxDataViewRenderer::GetAlignment() const
+{
+    return m_align;
+}
+
+int wxDataViewRenderer::CalculateAlignment() const
+{ 
+    if (m_align == wxDVR_DEFAULT_ALIGNMENT)
+    {
+        if (GetOwner() == NULL)
+           return wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL;
+           
+        return GetOwner()->GetAlignment() | wxALIGN_CENTRE_VERTICAL;
+    }
+    
+    return m_align;
+}
+
 // ---------------------------------------------------------
 // wxDataViewCustomRenderer
 // ---------------------------------------------------------
@@ -1160,7 +1187,7 @@ wxDataViewColumn::wxDataViewColumn( const wxBitmap &bitmap, wxDataViewRenderer *
     SetAlignment(align);
     SetFlags(flags);
 
-    Init(width < 0 ? wxDVC_TOGGLE_DEFAULT_WIDTH : width);
+    Init(width < 0 ? wxDVC_DEFAULT_WIDTH : width);
 }
 
 wxDataViewColumn::~wxDataViewColumn()
@@ -1265,7 +1292,7 @@ void wxDataViewHeaderWindowBase::SendEvent(wxEventType type, unsigned int n)
     parent->GetEventHandler()->ProcessEvent(le);
 }
 
-#if defined(__WXMSW__) && USE_NATIVE_HEADER_WINDOW
+#ifdef USE_NATIVE_HEADER_WINDOW
 
 #ifndef HDS_DRAGDROP
     #define HDS_DRAGDROP 0x0040
@@ -1321,6 +1348,9 @@ bool wxDataViewHeaderWindowMSW::Create( wxDataViewCtrl *parent, wxWindowID id,
         return false;
     }
 
+    m_imageList = new wxImageList( 16, 16 );
+    Header_SetImageList( (HWND) m_hWnd, m_imageList->GetHIMAGELIST() );
+
     // we need to subclass the m_hWnd to force wxWindow::HandleNotify
     // to call wxDataViewHeaderWindow::MSWOnNotify
     SubclassWin(m_hWnd);
@@ -1334,6 +1364,7 @@ bool wxDataViewHeaderWindowMSW::Create( wxDataViewCtrl *parent, wxWindowID id,
 
 wxDataViewHeaderWindowMSW::~wxDataViewHeaderWindow()
 {
+    delete m_imageList;
     UnsubclassWin();
 }
 
@@ -1356,6 +1387,8 @@ void wxDataViewHeaderWindowMSW::UpdateDisplay()
     // remove old columns
     for (int j=0, max=Header_GetItemCount((HWND)m_hWnd); j < max; j++)
         Header_DeleteItem((HWND)m_hWnd, 0);
+        
+    m_imageList->RemoveAll();
 
     // add the updated array of columns to the header control
     unsigned int cols = GetOwner()->GetColumnCount();
@@ -1368,10 +1401,19 @@ void wxDataViewHeaderWindowMSW::UpdateDisplay()
 
         HDITEM hdi;
         hdi.mask = HDI_TEXT | HDI_FORMAT | HDI_WIDTH;
+        if (col->GetBitmap().IsOk())
+        {
+           m_imageList->Add( col->GetBitmap() );
+           hdi.mask |= HDI_IMAGE;
+           hdi.iImage = m_imageList->GetImageCount()-1;
+        }
         hdi.pszText = (wxChar *) col->GetTitle().wx_str();
         hdi.cxy = col->GetWidth();
         hdi.cchTextMax = sizeof(hdi.pszText)/sizeof(hdi.pszText[0]);
         hdi.fmt = HDF_LEFT | HDF_STRING;
+        if (col->GetBitmap().IsOk())
+            hdi.fmt |= HDF_IMAGE;
+        
         //hdi.fmt &= ~(HDF_SORTDOWN|HDF_SORTUP);
 
         if (col->IsSortable() && GetOwner()->GetSortingColumn() == col)
@@ -1462,7 +1504,7 @@ bool wxDataViewHeaderWindowMSW::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARA
 
         case HDN_BEGINDRAG:
             // user has started to reorder a column
-            if (!GetColumn(nmHDR->iItem)->IsReorderable())
+            if ((nmHDR->iItem != -1) && (!GetColumn(nmHDR->iItem)->IsReorderable()))
             {
                 // veto it!
                 *result = TRUE;
@@ -1919,7 +1961,7 @@ void wxDataViewRenameTimer::Notify()
 //-----------------------------------------------------------------------------
 
 //The tree building helper, declared firstly
-void BuildTreeHelper( wxDataViewModel * model,  wxDataViewItem & item, wxDataViewTreeNode * node);
+static void BuildTreeHelper( wxDataViewModel * model,  wxDataViewItem & item, wxDataViewTreeNode * node);
 
 int LINKAGEMODE wxDataViewSelectionCmp( unsigned int row1, unsigned int row2 )
 {
@@ -1968,10 +2010,10 @@ wxDataViewMainWindow::wxDataViewMainWindow( wxDataViewCtrl *parent, wxWindowID i
 
     SetBackgroundStyle(wxBG_STYLE_CUSTOM);
 
-    m_penRule = wxPen(GetRuleColour(), 1, wxSOLID);
+    m_penRule = wxPen(GetRuleColour());
 
     //Here I compose a pen can draw black lines, maybe there are something system colour to use
-    m_penExpander = wxPen( wxColour(0,0,0), 1, wxSOLID );
+    m_penExpander = wxPen(wxColour(0,0,0));
     //Some new added code to deal with the tree structure
     m_root = new wxDataViewTreeNode( NULL );
     m_root->SetHasChildren(true);
@@ -2194,19 +2236,15 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
                     else
                         wxRendererNative::Get().DrawTreeItemButton( this, dc, rect, flag);
                 }
-                else
-                {
-                     // I am wondering whether we should draw dot lines between tree nodes
-                     if (node)
-                         delete node;
-                     // Yes, if the node does not have any child, it must be a leaf which
-                     // mean that it is a temporarily created by GetTreeNodeByRow
-                }
-
                  //force the expander column to left-center align
                  cell->SetAlignment( wxALIGN_CENTER_VERTICAL );
             }
-
+            if (node && !node->HasChildren())
+            {
+                // Yes, if the node does not have any child, it must be a leaf which
+                // mean that it is a temporarily created by GetTreeNodeByRow
+                wxDELETE(node)
+            }
 
             // cannot be bigger than allocated space
             wxSize size = cell->GetSize();
@@ -2216,7 +2254,7 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
             size.y = cell_rect.height;
 
             wxRect item_rect(cell_rect.GetTopLeft(), size);
-            int align = cell->GetAlignment();
+            int align = cell->CalculateAlignment();
 
             // horizontal alignment:
             item_rect.x = cell_rect.x;
@@ -2397,7 +2435,7 @@ bool wxDataViewMainWindow::ItemAdded(const wxDataViewItem & parent, const wxData
     return true;
 }
 
-void DestroyTreeHelper( wxDataViewTreeNode * node);
+static void DestroyTreeHelper( wxDataViewTreeNode * node);
 
 bool wxDataViewMainWindow::ItemDeleted(const wxDataViewItem& parent,
                                        const wxDataViewItem& item)
@@ -2455,16 +2493,11 @@ bool wxDataViewMainWindow::ItemDeleted(const wxDataViewItem& parent,
 
         node->GetNodes().Remove( n );
         sub -= n->GetSubTreeCount();
-        DestroyTreeHelper(n);
+        ::DestroyTreeHelper(n);
     }
     //Make the row number invalid and get a new valid one when user call GetRowCount
     m_count = -1;
     node->ChangeSubTreeCount(sub);
-    if( node->GetChildrenNumber() == 0)
-    {
-        node->GetParent()->GetNodes().Remove( node );
-        delete node;
-    }
 
     //Change the current row to the last row if the current exceed the max row number
     if( m_currentRow > GetRowCount() )
@@ -3071,7 +3104,7 @@ void wxDataViewMainWindow::OnExpanding( unsigned int row )
                if( node->GetChildrenNumber() == 0 )
                {
                    SortPrepare();
-                   BuildTreeHelper(GetOwner()->GetModel(), node->GetItem(), node);
+                   ::BuildTreeHelper(GetOwner()->GetModel(), node->GetItem(), node);
                }
                m_count = -1;
                UpdateDisplay();
@@ -3155,26 +3188,32 @@ wxDataViewTreeNode * wxDataViewMainWindow::FindNode( const wxDataViewItem & item
             if( node->GetChildrenNumber() == 0 )
             {
                 SortPrepare();
-                BuildTreeHelper(model, node->GetItem(), node);
+                ::BuildTreeHelper(model, node->GetItem(), node);
             }
 
             wxDataViewTreeNodes nodes = node->GetNodes();
-            unsigned int i = 0;
-            for (; i < nodes.GetCount(); i ++)
+            unsigned int i;
+            bool found = false;
+            
+            for (i = 0; i < nodes.GetCount(); i ++)
             {
                 if (nodes[i]->GetItem() == (**iter))
                 {
+                    if (nodes[i]->GetItem() == item)
+                       return nodes[i];
+                       
                     node = nodes[i];
+                    found = true;
                     break;
                 }
             }
-            if (i == nodes.GetCount())
+            if (!found)
                 return NULL;
         }
         else
             return NULL;
     }
-    return node;
+    return NULL;
 }
 
 void wxDataViewMainWindow::HitTest( const wxPoint & point, wxDataViewItem & item, wxDataViewColumn* &column )
@@ -3318,7 +3357,7 @@ int wxDataViewMainWindow::GetRowByItem(const wxDataViewItem & item)
     }
 }
 
-void BuildTreeHelper( wxDataViewModel * model,  wxDataViewItem & item, wxDataViewTreeNode * node)
+static void BuildTreeHelper( wxDataViewModel * model,  wxDataViewItem & item, wxDataViewTreeNode * node)
 {
     if( !model->IsContainer( item ) )
         return ;
@@ -3352,7 +3391,7 @@ void wxDataViewMainWindow::BuildTree(wxDataViewModel * model)
 {
     DestroyTree();
 
-    if (GetOwner()->GetModel()->IsIndexListModel())
+    if (GetOwner()->GetModel()->IsVirtualListModel())
     {
         m_count = -1 ;
         return;
@@ -3368,13 +3407,13 @@ void wxDataViewMainWindow::BuildTree(wxDataViewModel * model)
     m_count = -1 ;
 }
 
-void DestroyTreeHelper( wxDataViewTreeNode * node )
+static void DestroyTreeHelper( wxDataViewTreeNode * node )
 {
     if( node->GetNodeNumber() != 0 )
     {
         int len = node->GetNodeNumber();
         int i = 0 ;
-        wxDataViewTreeNodes nodes = node->GetNodes();
+        wxDataViewTreeNodes& nodes = node->GetNodes();
         for( ; i < len; i ++ )
         {
             DestroyTreeHelper(nodes[i]);
@@ -3387,7 +3426,7 @@ void wxDataViewMainWindow::DestroyTree()
 {
     if (m_root)
     {
-        DestroyTreeHelper(m_root);
+       ::DestroyTreeHelper(m_root);
         m_count = 0;
         m_root = NULL;
     }
@@ -3664,12 +3703,14 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event )
                         OnExpanding( current );
                 }
             }
+            if (node && !node->HasChildren())
+               delete node;
         }
         //If the user click the expander, we do not do editing even if the column with expander are editable
         if (m_lastOnSame && !expander && !ignore_other_columns)
         {
             if ((col == m_currentCol) && (current == m_currentRow) &&
-                (cell->GetMode() == wxDATAVIEW_CELL_EDITABLE) )
+                (cell->GetMode() & wxDATAVIEW_CELL_EDITABLE) )
             {
                 m_renameTimer->Start( 100, true );
             }
@@ -3702,28 +3743,18 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event )
             SendSelectionChangedEvent(GetItemByRow( m_currentRow ) );
         }
 
-        // notify cell about right click
         wxVariant value;
         model->GetValue( value, item, col->GetModelColumn() );
-        cell->SetValue( value );
-        wxRect cell_rect( xpos, current * m_lineHeight,
-                          col->GetWidth(), m_lineHeight );
-        if (!cell->RightClick( event.GetPosition(), cell_rect, model, item, col->GetModelColumn()))
-        {
-            wxWindow *parent = GetParent();
-            wxDataViewEvent le(wxEVT_COMMAND_DATAVIEW_ITEM_CONTEXT_MENU, parent->GetId());
-            le.SetItem( item );
-            le.SetEventObject(parent);
-            le.SetModel(GetOwner()->GetModel());
-            le.SetValue(value);
-
-            parent->GetEventHandler()->ProcessEvent(le);
-        }
+        wxWindow *parent = GetParent();
+        wxDataViewEvent le(wxEVT_COMMAND_DATAVIEW_ITEM_CONTEXT_MENU, parent->GetId());
+        le.SetItem( item );
+        le.SetEventObject(parent);
+        le.SetModel(GetOwner()->GetModel());
+        le.SetValue(value);
+        parent->GetEventHandler()->ProcessEvent(le);
     }
     else if (event.MiddleDown())
     {
-        // notify cell about middle click
-        // cell->...
     }
     if (event.LeftDown() || forceClick)
     {
@@ -3781,7 +3812,7 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event )
                 wxFAIL_MSG( _T("how did we get here?") );
             }
         }
-
+        
         if (m_currentRow != oldCurrentRow)
             RefreshRow( oldCurrentRow );
 
@@ -3792,6 +3823,18 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event )
 
         m_lastOnSame = !forceClick && ((col == oldCurrentCol) &&
                         (current == oldCurrentRow)) && oldWasSelected;
+
+        // Call LeftClick after everything else as under GTK+
+        if (cell->GetMode() & wxDATAVIEW_CELL_ACTIVATABLE)
+        {
+            // notify cell about right click
+            wxVariant value;
+            model->GetValue( value, item, col->GetModelColumn() );
+            cell->SetValue( value );
+            wxRect cell_rect( xpos, current * m_lineHeight,
+                          col->GetWidth(), m_lineHeight );
+            /* ignore ret */ cell->LeftClick( event.GetPosition(), cell_rect, model, item, col->GetModelColumn());
+        }
     }
 }
 
@@ -3838,6 +3881,12 @@ wxDataViewCtrl::~wxDataViewCtrl()
 {
     if (m_notifier)
         GetModel()->RemoveNotifier( m_notifier );
+
+    wxDataViewColumnList::const_iterator iter;
+    for (iter = m_cols.begin(); iter!=m_cols.end(); iter++)
+    {
+        delete *iter;
+    }
 }
 
 void wxDataViewCtrl::Init()
@@ -3849,8 +3898,11 @@ bool wxDataViewCtrl::Create(wxWindow *parent, wxWindowID id,
            const wxPoint& pos, const wxSize& size,
            long style, const wxValidator& validator )
 {
+    if ( (style & wxBORDER_MASK) == 0)
+        style |= wxBORDER_SUNKEN;
+    
     if (!wxControl::Create( parent, id, pos, size,
-                            style | wxScrolledWindowStyle|wxBORDER_SUNKEN, validator))
+                            style | wxScrolledWindowStyle, validator))
         return false;
 
     SetInitialSize(size);