2008-12-06 Ivan N. Zlatev <contact@i-nz.net>
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / DataGridView.cs
index 5577e7426379a2dec2fdfa5e556be891aebff19d..6c9c20f4f0b96920f5e00745c365673f2e667b25 100644 (file)
@@ -668,10 +668,13 @@ namespace System.Windows.Forms {
                                /// to the data cache, or the new cell is in a hidden
                                /// row.
                                /////////////////////////////////////////////////////
-                               if (value.DataGridView != this) {
+                               if (value.DataGridView != this)
                                        throw new ArgumentException("The cell is not in this DataGridView.");
-                               }
-                               SetCurrentCellAddressCore (value.ColumnIndex, value.RowIndex, false, true, false);
+
+                               if (value != null)
+                                       MoveCurrentCell (value.OwningColumn.Index, value.OwningRow.Index, true, false, false, true);
+                               else
+                                       MoveCurrentCell (-1, -1, true, false, false, true);
                        }
                }
 
@@ -2353,16 +2356,25 @@ namespace System.Windows.Forms {
                        return result;
                }
 
-               [MonoTODO ("Always includes partial rows")]
                public int DisplayedRowCount (bool includePartialRow)
                {
                        int result = 0;
-                       
-                       for (int i = first_row_index; i < Rows.Count; i++)
-                               if (Rows[i].Displayed)
+                       int rowTop = 0;
+
+                       if (ColumnHeadersVisible)
+                               rowTop += ColumnHeadersHeight;
+
+                       for (int index = first_row_index; index < Rows.Count; index++) {
+                               DataGridViewRow row = GetRowInternal (index);
+                               if (rowTop + row.Height < ClientSize.Height) {
                                        result++;
-                               else
+                                       rowTop += row.Height;
+                               } else {
+                                       if (includePartialRow)
+                                               result++;
                                        break;
+                               }
+                       }
                                        
                        return result;
                }
@@ -3538,6 +3550,10 @@ namespace System.Windows.Forms {
                                eh (this, e);
                }
 
+               internal void OnCellStateChangedInternal (DataGridViewCellStateChangedEventArgs e) {
+                       this.OnCellStateChanged (e);
+               }
+
                protected virtual void OnCellStateChanged (DataGridViewCellStateChangedEventArgs e)
                {
                        DataGridViewCellStateChangedEventHandler eh = (DataGridViewCellStateChangedEventHandler)(Events [CellStateChangedEvent]);
@@ -3910,7 +3926,7 @@ namespace System.Windows.Forms {
                {
                        base.OnHandleCreated(e);
                        
-                       if (Rows.Count > 0 && Columns.Count > 0)
+                       if (CurrentCell == null && Rows.Count > 0 && Columns.Count > 0)
                                MoveCurrentCell (ColumnDisplayIndexToIndex (0), 0, true, false, false, false);
                }
 
@@ -4188,11 +4204,12 @@ namespace System.Windows.Forms {
                        }
 
                        if (hitTest.Type == DataGridViewHitTestType.Cell) {
+                               row = rows [hitTest.RowIndex];
+                               cell = row.Cells [hitTest.ColumnIndex];
+                               SetCurrentCellAddressCore (cell.ColumnIndex, cell.RowIndex, false, true, true);
                                cellBounds = GetCellDisplayRectangle (hitTest.ColumnIndex, hitTest.RowIndex, false);
                                OnCellMouseDown (new DataGridViewCellMouseEventArgs (hitTest.ColumnIndex, hitTest.RowIndex, e.X - cellBounds.X, e.Y - cellBounds.Y, e));
                                OnCellClick (new DataGridViewCellEventArgs (hitTest.ColumnIndex, hitTest.RowIndex));
-                               row = rows [hitTest.RowIndex];
-                               cell = row.Cells [hitTest.ColumnIndex];
                        }
                        
                        DoSelectionOnMouseDown (hitTest);
@@ -4206,7 +4223,6 @@ namespace System.Windows.Forms {
                                return;
                        }
                        
-                       SetCurrentCellAddressCore (cell.ColumnIndex, cell.RowIndex, false, true, true);
                        Invalidate();
                        return;
                }
@@ -4491,7 +4507,6 @@ namespace System.Windows.Forms {
                        gridWidth = rowHeadersVisible ? rowHeadersWidth : 0;
                        gridHeight = 0;
                        
-                       int rows_displayed = 0;
                        int first_row_height = Rows.Count > 0 ? Rows[Math.Min (Rows.Count - 1, first_row_index)].Height : 0;
 //                     int room_left = this.Height;
                        
@@ -4531,9 +4546,7 @@ namespace System.Windows.Forms {
                                bounds.Y += bounds.Height;
                                bounds.X = BorderWidth;
                                
-                               if (bounds.Y < ClientSize.Height - (horizontalScrollBar.Visible ? horizontalScrollBar.Height : 0))
-                                       rows_displayed++;
-                               else
+                               if (bounds.Y >= ClientSize.Height - (horizontalScrollBar.Visible ? horizontalScrollBar.Height : 0))
                                        break;
                                        
                                gridHeight += row.Height;
@@ -4786,7 +4799,21 @@ namespace System.Windows.Forms {
                        if (eh != null) eh (this, e);
                }
 
-               protected internal virtual void OnRowsRemoved (DataGridViewRowsRemovedEventArgs e)
+               internal void OnRowsRemovedInternal (DataGridViewRowsRemovedEventArgs e)
+               {
+                       if (selected_rows != null)
+                               selected_rows.InternalClear ();
+                       if (selected_columns != null)
+                               selected_columns.InternalClear ();
+
+                       if (Rows.Count > 0 && Columns.Count > 0 && currentCell != null && 
+                           currentCell.RowIndex >= e.RowIndex)
+                               MoveCurrentCell (0, Math.Min (e.RowIndex, Rows.Count - 2), true, false, false, true);
+                       Invalidate ();
+                       OnRowsRemoved (e);
+               }
+
+               protected virtual void OnRowsRemoved (DataGridViewRowsRemovedEventArgs e)
                {
                        DataGridViewRowsRemovedEventHandler eh = (DataGridViewRowsRemovedEventHandler)(Events [RowsRemovedEvent]);
                        if (eh != null) eh (this, e);
@@ -4954,14 +4981,6 @@ namespace System.Windows.Forms {
                                        Rows.RemoveAt (row.Index);
                        }
 
-                       if (selected_rows != null)
-                               selected_rows.InternalClear ();
-                       if (selected_columns != null)
-                               selected_columns.InternalClear ();
-
-                       SetSelectedCellCore (0, Math.Min (index, Rows.Count - 1), true);
-                       Invalidate ();
-                       
                        return true;
                }
 
@@ -5323,15 +5342,17 @@ namespace System.Windows.Forms {
                        if (setAnchorCellAddress)
                                anchor_cell = new Point (columnIndex, rowIndex);
 
-                       DataGridViewCell oldCell = CurrentCell;
-                       currentCell = cell;
-                       currentCellAddress = new Point (columnIndex, rowIndex);
-                       if (currentCell != oldCell) {
-                               if (oldCell != null) {
-                                       EndEdit ();
-                                       OnCellLeave (new DataGridViewCellEventArgs(oldCell.ColumnIndex, oldCell.RowIndex));
-                                       OnRowLeave (new DataGridViewCellEventArgs (oldCell.ColumnIndex, oldCell.RowIndex));
+                       if (cell != currentCell) {
+                               if (currentCell != null) {
+                                       if (currentCell.IsInEditMode)
+                                               EndEdit ();
+                                       OnCellLeave (new DataGridViewCellEventArgs(currentCell.ColumnIndex, currentCell.RowIndex));
+                                       OnRowLeave (new DataGridViewCellEventArgs (currentCell.ColumnIndex, currentCell.RowIndex));
                                }
+
+                               currentCell = cell;
+                               currentCellAddress = new Point (columnIndex, rowIndex);
+
                                UpdateBindingPosition (currentCell.RowIndex);
                                OnRowEnter (new DataGridViewCellEventArgs (cell.ColumnIndex, cell.RowIndex));
                                OnCellEnter (new DataGridViewCellEventArgs(cell.ColumnIndex, cell.RowIndex));
@@ -5372,6 +5393,8 @@ namespace System.Windows.Forms {
                        } else if (selected && !selected_columns.Contains (col)) {
                                selected_columns.InternalAdd (col);
                        }
+
+                       Invalidate();
                }
 
                internal void SetSelectedRowCoreInternal (int rowIndex, bool selected) {
@@ -5391,6 +5414,8 @@ namespace System.Windows.Forms {
                        } else if (selected && !selected_rows.Contains (row)) {
                                selected_rows.InternalAdd (row);
                        }
+
+                       Invalidate();
                }
 
                protected override void WndProc (ref Message m)
@@ -5454,12 +5479,14 @@ namespace System.Windows.Forms {
                internal void OnVScrollBarScroll (object sender, ScrollEventArgs e)
                {
                        verticalScrollingOffset = e.NewValue;
+                       if (Rows.Count == 0)
+                               return;
+
                        int top = 0;
                        
                        for (int index = 0; index < Rows.Count; index++) {
                                DataGridViewRow row = Rows[index];
-                               
-                               if (e.NewValue <= top + row.Height) {
+                               if (e.NewValue < top + row.Height) {
                                        if (first_row_index != index) {
                                                first_row_index = index;
                                                Invalidate ();
@@ -5472,10 +5499,7 @@ namespace System.Windows.Forms {
                                top += row.Height;
                        }
                        
-                       if (Rows.Count == 0)
-                               return;
-                               
-                       first_row_index = Rows.Count - DisplayedRowCount (false) + 1;
+                       first_row_index = Rows.Count - DisplayedRowCount (false);
                        Invalidate ();
                        OnScroll (e);
                }
@@ -5594,7 +5618,8 @@ namespace System.Windows.Forms {
                        case DataGridViewAutoSizeColumnMode.AllCells:
                        case DataGridViewAutoSizeColumnMode.DisplayedCells:
                        case DataGridViewAutoSizeColumnMode.DisplayedCellsExceptHeader:
-                               size  = CalculateColumnCellWidth (columnIndex, col.InheritedAutoSizeMode);
+                               size  = Math.Max (CalculateColumnCellWidth (columnIndex, col.InheritedAutoSizeMode), 
+                                                 col.HeaderCell.ContentBounds.Width);
                                break;
                        case DataGridViewAutoSizeColumnMode.ColumnHeader:
                                size = col.HeaderCell.ContentBounds.Width;
@@ -5744,12 +5769,18 @@ namespace System.Windows.Forms {
                                (list as DataView).Table.ColumnChanged += OnTableColumnChanged;
                                (list as DataView).Table.TableCleared += OnTableCleared;
                        }
-                       
+
                        // Add the rows
                        foreach (object element in list)
                                AddBoundRow (element);
                }
 
+               private void OnBindingSourceDataSourceChanged (object sender, EventArgs args)
+               {
+                       ClearBinding();
+                       DoBinding();
+               }
+
                private void AddBoundRow (object element)
                {
                        // Don't add rows if there are no columns
@@ -5828,6 +5859,11 @@ namespace System.Windows.Forms {
                                        (dataSource as DataView).Table.ColumnChanged -= OnTableColumnChanged;
                                } else if (dataSource is DataTable)
                                        ((dataSource as IListSource).GetList () as DataView).ListChanged -= OnListChanged;
+
+                               if (dataSource is IBindingList)
+                                       (dataSource as IBindingList).ListChanged -= OnListChanged;
+                               if (dataSource is BindingSource)
+                                       (dataSource as BindingSource).DataSourceChanged -= OnBindingSourceDataSourceChanged;
                        }
                }
                
@@ -5852,30 +5888,41 @@ namespace System.Windows.Forms {
                                        (value as DataSet).Tables.CollectionChanged += OnDataSetTableChanged;
                                        value = (value as DataSet).Tables[dataMember];
                                }
+                               
                                if (value is BindingSource)
-                                       value = (value as BindingSource).List;
-                                       
-                               if (value is IList)
+                                       BindBindingSource (value as BindingSource);
+                               else if (value is IBindingListView)
+                                       BindIBindingListView (value as IBindingListView);
+                               else if (value is IBindingList)
+                                       BindIBindingList (value as IBindingList);
+                               else if (value is IList)
                                        BindIList (value as IList);
                                else if (value is IListSource)
                                        BindIListSource (value as IListSource);
-                               else if (value is IBindingList)
-                                       BindIBindingList (value as IBindingList);
-                               else if (value is IBindingListView)
-                                       BindIBindingListView (value as IBindingListView);
 
                                OnDataBindingComplete (new DataGridViewBindingCompleteEventArgs (ListChangedType.Reset));
                        }
 
+                       if (Rows.Count > 0 && Columns.Count > 0)
+                               MoveCurrentCell (0, 0, true, false, false, false);
+                       PerformLayout();
                        Invalidate ();
                }
                
+               private void BindBindingSource (BindingSource bindingSource)
+               {
+                       BindIList (bindingSource.List);
+                       bindingSource.ListChanged += OnBindingSourceDataSourceChanged;
+                       bindingSource.DataSourceChanged += OnBindingSourceDataSourceChanged;
+               }
+
                private void BindIListSource (IListSource list) {
-                       BindIList(list.GetList());
+                       BindIList (list.GetList());
                }
 
                private void BindIBindingList (IBindingList list) {
-                       BindIList(list);
+                       BindIList (list);
+                       list.ListChanged += OnListChanged;
                }
 
                private void BindIBindingListView (IBindingListView list) {
@@ -5884,6 +5931,8 @@ namespace System.Windows.Forms {
 
                private void MoveCurrentCell (int x, int y, bool select, bool isControl, bool isShift, bool scroll)
                {
+                       SetCurrentCellAddressCore (x, y, true, false, false);
+
                        bool full_row_selected = Rows.SharedRow(CurrentCellAddress.Y).Selected;
                        bool full_col_selected = Columns[CurrentCellAddress.X].Selected;
                        
@@ -5902,17 +5951,6 @@ namespace System.Windows.Forms {
                        else if (mode == DataGridViewSelectionMode.ColumnHeaderSelect)
                                mode = DataGridViewSelectionMode.CellSelect;
                        
-                       // End edit if the old cell was editing, and fire CellLeave for the old cell
-                       if (currentCell != null) {
-                               OnCellLeave (new DataGridViewCellEventArgs (currentCell.ColumnIndex, currentCell.RowIndex));
-                                       
-                               if (currentCell.IsInEditMode)
-                                       EndEdit ();
-                       }
-                       
-                       // Move CurrentCell
-                       SetCurrentCellAddressCore (x, y, true, false, false);
-                       
                        // If the current cell isn't visible, scroll to it
                        if (scroll) {
                                int disp_x = ColumnIndexToDisplayIndex (x);
@@ -5931,10 +5969,10 @@ namespace System.Windows.Forms {
                                }
 
                                int disp_y = y;
+                               int displayedRowsCount = DisplayedRowCount (false);
+                               int delta_y = 0;
 
                                if (disp_y < first_row_index) {
-                                       int delta_y = 0;
-
                                        if (disp_y == 0)
                                                delta_y = verticalScrollBar.Value;
                                        else
@@ -5943,13 +5981,11 @@ namespace System.Windows.Forms {
 
                                        verticalScrollBar.SafeValueSet (verticalScrollBar.Value - delta_y);
                                        OnVScrollBarScroll (this, new ScrollEventArgs (ScrollEventType.ThumbPosition, verticalScrollBar.Value));
-                               } else if (disp_y > first_row_index + DisplayedRowCount (false) - 2) {
-                                       int delta_y = 0;
-                                       
+                               } else if (disp_y > first_row_index + displayedRowsCount - 1) {
                                        if (disp_y == Rows.Count - 1)
                                                delta_y = verticalScrollBar.Maximum - verticalScrollBar.Value;
                                        else
-                                               for (int i = first_row_index + DisplayedRowCount (false) - 2; i < disp_y; i++)
+                                               for (int i = first_row_index + displayedRowsCount - 1; i < disp_y; i++)
                                                        delta_y += GetRowInternal (i).Height;
 
                                        verticalScrollBar.SafeValueSet (verticalScrollBar.Value + delta_y);
@@ -5976,9 +6012,6 @@ namespace System.Windows.Forms {
                                        break;
                        }
                        
-                       // Raise CellEnter
-                       OnCellEnter (new DataGridViewCellEventArgs (currentCell.ColumnIndex, currentCell.RowIndex));
-                       
                        Invalidate ();
                }
                
@@ -5996,11 +6029,15 @@ namespace System.Windows.Forms {
                {
                        switch (args.ListChangedType) {
                                case ListChangedType.ItemAdded:
-                                       AddBoundRow ((sender as DataView)[args.NewIndex]);
+                                       AddBoundRow ((sender as IBindingList)[args.NewIndex]);
                                        break;
                                case ListChangedType.ItemDeleted:
                                        Rows.RemoveAt (args.NewIndex);
                                        break;
+                               default:
+                                       ClearBinding ();
+                                       DoBinding ();
+                                       break;
                        }
                        
                        Invalidate ();