]> git.saurik.com Git - wxWidgets.git/blobdiff - src/generic/datavgen.cpp
More efficient access to name and value
[wxWidgets.git] / src / generic / datavgen.cpp
index 0823c1752bba63def718889e95542f0cb1d6326c..2f24a4a9939462287f1d88668f5462aa80f0f666 100644 (file)
@@ -95,7 +95,7 @@ void wxDataViewColumn::Init(int width, wxAlignment align, int flags)
     m_sort = false;
     m_sortAscending = true;
 }
-    
+
 void wxDataViewColumn::UpdateDisplay()
 {
     if (m_owner)
@@ -411,6 +411,7 @@ public:
                             const wxString &name = wxT("wxdataviewctrlmainwindow") );
     virtual ~wxDataViewMainWindow();
 
+    bool IsList() const { return GetOwner()->GetModel()->IsListModel(); }
     bool IsVirtualList() const { return m_root == NULL; }
 
     // notifications from wxDataViewModel
@@ -470,6 +471,7 @@ public:
     void ScrollWindow( int dx, int dy, const wxRect *rect = NULL );
     void ScrollTo( int rows, int column );
 
+    unsigned GetCurrentRow() const { return m_currentRow; }
     bool HasCurrentRow() { return m_currentRow != (unsigned int)-1; }
     void ChangeCurrentRow( unsigned int row );
 
@@ -844,12 +846,12 @@ bool wxDataViewToggleRenderer::Render( wxRect cell, wxDC *dc, int WXUNUSED(state
     return true;
 }
 
-bool wxDataViewToggleRenderer::Activate( wxRect WXUNUSED(cell),
-                                        wxDataViewModel *model,
-                                        const wxDataViewItem & item, unsigned int col)
+void wxDataViewToggleRenderer::WXOnActivate(wxDataViewModel *model,
+                                            const wxVariant& valueOld,
+                                            const wxDataViewItem & item,
+                                            unsigned int col)
 {
-    model->ChangeValue(!m_toggle, item, col);
-    return true;
+    model->ChangeValue(!valueOld.GetBool(), item, col);
 }
 
 wxSize wxDataViewToggleRenderer::GetSize() const
@@ -1005,24 +1007,23 @@ wxSize wxDataViewDateRenderer::GetSize() const
     return wxSize(x,y+d);
 }
 
-bool wxDataViewDateRenderer::Activate( wxRect WXUNUSED(cell), wxDataViewModel *model,
-                                    const wxDataViewItem & item, unsigned int col )
+void wxDataViewDateRenderer::WXOnActivate(wxDataViewModel *model,
+                                          const wxVariant& valueOld,
+                                          const wxDataViewItem & item,
+                                          unsigned int col )
 {
-    wxVariant variant;
-    model->GetValue( variant, item, col );
-    wxDateTime value = variant.GetDateTime();
+    wxDateTime dtOld = valueOld.GetDateTime();
 
 #if wxUSE_DATE_RENDERER_POPUP
     wxDataViewDateRendererPopupTransient *popup = new wxDataViewDateRendererPopupTransient(
-        GetOwner()->GetOwner()->GetParent(), &value, model, item, col);
+        GetOwner()->GetOwner()->GetParent(), &dtOld, model, item, col);
     wxPoint pos = wxGetMousePosition();
     popup->Move( pos );
     popup->Layout();
     popup->Popup( popup->m_cal );
 #else // !wxUSE_DATE_RENDERER_POPUP
-    wxMessageBox(value.Format());
+    wxMessageBox(dtOld.Format());
 #endif // wxUSE_DATE_RENDERER_POPUP/!wxUSE_DATE_RENDERER_POPUP
-    return true;
 }
 
 // ---------------------------------------------------------
@@ -1378,7 +1379,7 @@ wxDragResult wxDataViewMainWindow::OnDragOver( wxDataFormat format, wxCoord x,
     m_owner->CalcUnscrolledPosition( xx, yy, &xx, &yy );
     unsigned int row = GetLineAt( yy );
 
-    if ((row >= GetRowCount()) || (yy > GetEndOfLastCol()))
+    if ((row >= GetRowCount()) || (xx > GetEndOfLastCol()))
     {
         RemoveDropHint();
         return wxDragNone;
@@ -1424,7 +1425,7 @@ bool wxDataViewMainWindow::OnDrop( wxDataFormat format, wxCoord x, wxCoord y )
     m_owner->CalcUnscrolledPosition( xx, yy, &xx, &yy );
     unsigned int row = GetLineAt( yy );
 
-    if ((row >= GetRowCount()) || (yy > GetEndOfLastCol()))
+    if ((row >= GetRowCount()) || (xx > GetEndOfLastCol()))
         return false;
 
     wxDataViewItem item = GetItemByRow( row );
@@ -1453,7 +1454,7 @@ wxDragResult wxDataViewMainWindow::OnData( wxDataFormat format, wxCoord x, wxCoo
     m_owner->CalcUnscrolledPosition( xx, yy, &xx, &yy );
     unsigned int row = GetLineAt( yy );
 
-    if ((row >= GetRowCount()) || (yy > GetEndOfLastCol()))
+    if ((row >= GetRowCount()) || (xx > GetEndOfLastCol()))
         return wxDragNone;
 
     wxDataViewItem item = GetItemByRow( row );
@@ -1498,7 +1499,7 @@ wxBitmap wxDataViewMainWindow::CreateItemBitmap( unsigned int row, int &indent )
     }
 
     indent = 0;
-    if (!IsVirtualList())
+    if (!IsList())
     {
         wxDataViewTreeNode *node = GetTreeNodeByRow(row);
         indent = GetOwner()->GetIndent() * node->GetIndentLevel();
@@ -1765,7 +1766,7 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
 
             // deal with the expander
             int indent = 0;
-            if ((!IsVirtualList()) && (col == expander))
+            if ((!IsList()) && (col == expander))
             {
                 // Calculate the indent first
                 indent = GetOwner()->GetIndent() * node->GetIndentLevel();
@@ -1990,9 +1991,12 @@ bool wxDataViewMainWindow::ItemDeleted(const wxDataViewItem& parent,
 
     wxDataViewTreeNode * node = FindNode(parent);
 
-    wxCHECK_MSG( node != NULL, false, "item not found" );
-    wxCHECK_MSG( node->GetChildren().Index( item.GetID() ) != wxNOT_FOUND,
-                 false, "item not found" );
+    // Notice that it is possible that the item being deleted is not in the
+    // tree at all, for example we could be deleting a never shown (because
+    // collapsed) item in a tree model. So it's not an error if we don't know
+    // about this item, just return without doing anything then.
+    if ( !node || node->GetChildren().Index(item.GetID()) == wxNOT_FOUND )
+        return false;
 
     int sub = -1;
     node->GetChildren().Remove( item.GetID() );
@@ -2793,7 +2797,7 @@ wxDataViewEvent wxDataViewMainWindow::SendExpanderEvent( wxEventType type,
 
 bool wxDataViewMainWindow::IsExpanded( unsigned int row ) const
 {
-    if (IsVirtualList())
+    if (IsList())
         return false;
 
     wxDataViewTreeNode * node = GetTreeNodeByRow(row);
@@ -2811,7 +2815,7 @@ bool wxDataViewMainWindow::IsExpanded( unsigned int row ) const
 
 bool wxDataViewMainWindow::HasChildren( unsigned int row ) const
 {
-    if (IsVirtualList())
+    if (IsList())
         return false;
 
     wxDataViewTreeNode * node = GetTreeNodeByRow(row);
@@ -2829,7 +2833,7 @@ bool wxDataViewMainWindow::HasChildren( unsigned int row ) const
 
 void wxDataViewMainWindow::Expand( unsigned int row )
 {
-    if (IsVirtualList())
+    if (IsList())
         return;
 
     wxDataViewTreeNode * node = GetTreeNodeByRow(row);
@@ -2885,7 +2889,7 @@ void wxDataViewMainWindow::Expand( unsigned int row )
 
 void wxDataViewMainWindow::Collapse(unsigned int row)
 {
-    if (IsVirtualList())
+    if (IsList())
         return;
 
     wxDataViewTreeNode *node = GetTreeNodeByRow(row);
@@ -3084,7 +3088,7 @@ wxRect wxDataViewMainWindow::GetItemRect( const wxDataViewItem & item,
     // to get the correct x position where the actual text is
     int indent = 0;
     int row = GetRowByItem(item);
-    if (!IsVirtualList() && (column == 0 || GetOwner()->GetExpanderColumn() == column) )
+    if (!IsList() && (column == 0 || GetOwner()->GetExpanderColumn() == column) )
     {
         wxDataViewTreeNode* node = GetTreeNodeByRow(row);
         indent = GetOwner()->GetIndent() * node->GetIndentLevel();
@@ -3282,7 +3286,15 @@ void wxDataViewMainWindow::DestroyTree()
 
 void wxDataViewMainWindow::OnChar( wxKeyEvent &event )
 {
-    if ( GetParent()->HandleAsNavigationKey(event) )
+    wxWindow * const parent = GetParent();
+
+    // propagate the char event upwards
+    wxKeyEvent eventForParent(event);
+    eventForParent.SetEventObject(parent);
+    if ( parent->ProcessWindowEvent(eventForParent) )
+        return;
+
+    if ( parent->HandleAsNavigationKey(event) )
         return;
 
     // no item -> nothing to do
@@ -3300,7 +3312,6 @@ void wxDataViewMainWindow::OnChar( wxKeyEvent &event )
     {
         case WXK_RETURN:
             {
-                wxWindow *parent = GetParent();
                 wxDataViewEvent le(wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED,
                                    parent->GetId());
                 le.SetItem( GetItemByRow(m_currentRow) );
@@ -3323,7 +3334,7 @@ void wxDataViewMainWindow::OnChar( wxKeyEvent &event )
         // Add the process for tree expanding/collapsing
         case WXK_LEFT:
         {
-            if (IsVirtualList())
+            if (IsList())
                break;
 
             wxDataViewTreeNode* node = GetTreeNodeByRow(m_currentRow);
@@ -3464,7 +3475,7 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event )
 
     // Test whether the mouse is hovered on the tree item button
     bool hoverOverExpander = false;
-    if ((!IsVirtualList()) && (GetOwner()->GetExpanderColumn() == col))
+    if ((!IsList()) && (GetOwner()->GetExpanderColumn() == col))
     {
         wxDataViewTreeNode * node = GetTreeNodeByRow(current);
         if( node!=NULL && node->HasChildren() )
@@ -3585,14 +3596,20 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event )
         {
             if ((!ignore_other_columns) && (cell->GetMode() == wxDATAVIEW_CELL_ACTIVATABLE))
             {
+                const unsigned colIdx = col->GetModelColumn();
+
+                wxVariant value;
+                model->GetValue( value, item, colIdx );
+
+                cell->WXOnActivate(model, value, item, colIdx);
+
                 if ( wxDataViewCustomRenderer *custom = cell->WXGetAsCustom() )
                 {
-                    wxVariant value;
-                    model->GetValue( value, item, col->GetModelColumn() );
-                    custom->SetValue( value );
+                    cell->SetValue( value );
+
                     wxRect cell_rect( xpos, GetLineStart( current ),
                                     col->GetWidth(), GetLineHeight( current ) );
-                    custom->Activate( cell_rect, model, item, col->GetModelColumn() );
+                    custom->Activate( cell_rect, model, item, colIdx );
                 }
             }
             else
@@ -3770,7 +3787,44 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event )
                 custom->SetValue( value );
                 wxRect cell_rect( xpos, GetLineStart( current ),
                                   col->GetWidth(), GetLineHeight( current ) );
-                 /* ignore ret */ custom->LeftClick( event.GetPosition(), cell_rect,
+
+                // Report position relative to the cell's custom area, i.e.
+                // no the entire space as given by the control but the one
+                // used by the renderer after calculation of alignment etc.
+
+                // adjust the rectangle ourselves to account for the alignment
+                wxRect rectItem = cell_rect;
+                const int align = custom->GetAlignment();
+                if ( align != wxDVR_DEFAULT_ALIGNMENT )
+                {
+                    const wxSize size = custom->GetSize();
+
+                    if ( size.x >= 0 && size.x < cell_rect.width )
+                    {
+                        if ( align & wxALIGN_CENTER_HORIZONTAL )
+                            rectItem.x += (cell_rect.width - size.x)/2;
+                        else if ( align & wxALIGN_RIGHT )
+                            rectItem.x += cell_rect.width - size.x;
+                        // else: wxALIGN_LEFT is the default
+                    }
+
+                    if ( size.y >= 0 && size.y < cell_rect.height )
+                    {
+                        if ( align & wxALIGN_CENTER_VERTICAL )
+                            rectItem.y += (cell_rect.height - size.y)/2;
+                        else if ( align & wxALIGN_BOTTOM )
+                            rectItem.y += cell_rect.height - size.y;
+                        // else: wxALIGN_TOP is the default
+                    }
+                }
+
+                wxPoint pos( event.GetPosition() );
+                pos.x -= rectItem.x;
+                pos.y -= rectItem.y;
+
+                m_owner->CalcUnscrolledPosition( pos.x, pos.y, &pos.x, &pos.y );
+
+                 /* ignore ret */ custom->LeftClick( pos, cell_rect,
                                   model, item, col->GetModelColumn());
             }
         }
@@ -3835,9 +3889,13 @@ void wxDataViewCtrl::Init()
     m_headerArea = NULL;
 }
 
-bool wxDataViewCtrl::Create(wxWindow *parent, wxWindowID id,
-                            const wxPoint& pos, const wxSize& size,
-                            long style, const wxValidator& validator )
+bool wxDataViewCtrl::Create(wxWindow *parent,
+                            wxWindowID id,
+                            const wxPoint& pos,
+                            const wxSize& size,
+                            long style,
+                            const wxValidator& validator,
+                            const wxString& name)
 {
 //    if ( (style & wxBORDER_MASK) == 0)
 //        style |= wxBORDER_SUNKEN;
@@ -3845,7 +3903,7 @@ bool wxDataViewCtrl::Create(wxWindow *parent, wxWindowID id,
     Init();
 
     if (!wxControl::Create( parent, id, pos, size,
-                            style | wxScrolledWindowStyle, validator))
+                            style | wxScrolledWindowStyle, validator, name))
         return false;
 
     SetInitialSize(size);
@@ -3856,6 +3914,11 @@ bool wxDataViewCtrl::Create(wxWindow *parent, wxWindowID id,
 
     m_clientArea = new wxDataViewMainWindow( this, wxID_ANY );
 
+    // We use the cursor keys for moving the selection, not scrolling, so call
+    // this method to ensure wxScrollHelperEvtHandler doesn't catch all
+    // keyboard events forwarded to us from wxListMainWindow.
+    DisableKeyboardScrolling();
+
     if (HasFlag(wxDV_NO_HEADER))
         m_headerArea = NULL;
     else
@@ -4083,7 +4146,7 @@ int wxDataViewCtrl::GetColumnPosition( const wxDataViewColumn *column ) const
         if (column==col)
             return i;
     }
-    
+
     return wxNOT_FOUND;
 #else
     // This returns the position in pixels which is not what we want.
@@ -4112,6 +4175,24 @@ wxDataViewColumn *wxDataViewCtrl::GetSortingColumn() const
                                             : GetColumn(m_sortingColumnIdx);
 }
 
+wxDataViewItem wxDataViewCtrl::DoGetCurrentItem() const
+{
+    return GetItemByRow(m_clientArea->GetCurrentRow());
+}
+
+void wxDataViewCtrl::DoSetCurrentItem(const wxDataViewItem& item)
+{
+    const int row = m_clientArea->GetRowByItem(item);
+
+    const unsigned oldCurrent = m_clientArea->GetCurrentRow();
+    if ( static_cast<unsigned>(row) != oldCurrent )
+    {
+        m_clientArea->ChangeCurrentRow(row);
+        m_clientArea->RefreshRow(oldCurrent);
+        m_clientArea->RefreshRow(row);
+    }
+}
+
 // Selection code with wxDataViewItem as parameters
 wxDataViewItem wxDataViewCtrl::GetSelection() const
 {
@@ -4167,9 +4248,9 @@ void wxDataViewCtrl::Select( const wxDataViewItem & item )
         // Unselect all rows before select another in the single select mode
         if (m_clientArea->IsSingleSel())
             m_clientArea->SelectAllRows(false);
-            
+
         m_clientArea->SelectRow(row, true);
-        
+
         // Also set focus to the selected item
         m_clientArea->ChangeCurrentRow( row );
     }