2009-03-19 Ivan N. Zlatev <contact@i-nz.net>
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / DataGridView.cs
index b1df128896065403ad6904737848927fcf0af16e..80842f9a84e7feedf14b308bcadc803bcec55d1c 100644 (file)
@@ -587,7 +587,7 @@ namespace System.Windows.Forms {
                                        }
                                }
                                else if (value > columns.Count) {
-                                       for (int i = 0; i < value; i++) {
+                                       for (int i = columns.Count; i < value; i++) {
                                                DataGridViewTextBoxColumn col = new DataGridViewTextBoxColumn ();
                                                columns.Add(col);
                                        }
@@ -714,7 +714,7 @@ namespace System.Windows.Forms {
                        set {
                                if (dataMember != value) {
                                        dataMember = value;
-                                       if (IsHandleCreated)
+                                       if (BindingContext != null)
                                                ReBind ();
                                        OnDataMemberChanged(EventArgs.Empty);
                                }
@@ -738,7 +738,7 @@ namespace System.Windows.Forms {
                                        
                                ClearBinding ();
                                dataSource = value;
-                               if (IsHandleCreated)
+                               if (BindingContext != null)
                                        ReBind ();
                                OnDataSourceChanged (EventArgs.Empty);
                        }
@@ -1031,9 +1031,6 @@ namespace System.Windows.Forms {
                                        for (int i = rows.Count; i < value; i++) {
                                                DataGridViewRow row = (DataGridViewRow) RowTemplateFull;
                                                rows.AddInternal (row, false);
-                                               
-                                               foreach (DataGridViewColumn col in columns)
-                                                       row.Cells.Add (col.CellTemplate.Clone () as DataGridViewCell);
                                        }
                                }
                        }
@@ -1137,7 +1134,6 @@ namespace System.Windows.Forms {
                        }
                        set {
                                rowTemplate = value;
-                               rowTemplate.SetDataGridView(this);
                        }
                }
 
@@ -2412,9 +2408,15 @@ namespace System.Windows.Forms {
                        if (ColumnHeadersVisible)
                                rowTop += ColumnHeadersHeight;
 
+                       Size visibleClientArea = ClientSize;
+                       if (verticalScrollBar.Visible)
+                               visibleClientArea.Width -= verticalScrollBar.Width;
+                       if (horizontalScrollBar.Visible)
+                               visibleClientArea.Height -= horizontalScrollBar.Height;
+
                        for (int index = first_row_index; index < Rows.Count; index++) {
                                DataGridViewRow row = GetRowInternal (index);
-                               if (rowTop + row.Height <= ClientSize.Height) {
+                               if (rowTop + row.Height <= visibleClientArea.Height) {
                                        result++;
                                        rowTop += row.Height;
                                } else {
@@ -2512,7 +2514,10 @@ namespace System.Windows.Forms {
                        }
                        
                        for (int i = first_row_index; i < Rows.Count; i++) {
-                               if (i == rowIndex) {
+                               if (!rows[i].Visible)
+                                       continue;
+                                       
+                               if (rows[i].Index == rowIndex) {
                                        h = rows [i].Height;
                                        break;
                                }
@@ -2772,13 +2777,17 @@ namespace System.Windows.Forms {
                        if (ColumnHeadersVisible)
                                y += ColumnHeadersHeight;
 
+
                        for (int i = first_row_index; i < Rows.Count; i++) {
-                               if (i == rowIndex) {
-                                       h = rows[i].Height;
+                               if (!rows[i].Visible)
+                                       continue;
+                                       
+                               if (rows[i].Index == rowIndex) {
+                                       h = rows [i].Height;
                                        break;
                                }
-
-                               y += rows[i].Height;
+                               
+                               y += rows [i].Height;
                        }
 
                        return new Rectangle (0, y, Width, h);
@@ -2814,6 +2823,8 @@ namespace System.Windows.Forms {
                        
                        for (int i = first_row_index; i < Rows.Count; i++) {
                                DataGridViewRow row = Rows[i];
+                               if (!row.Visible)
+                                       continue;
                                
                                if (y > top && y <= (top + row.Height)) {
                                        rowindex = i;
@@ -3167,6 +3178,8 @@ namespace System.Windows.Forms {
                        }
                        
                        foreach (DataGridViewRow row in Rows) {
+                               if (!row.Visible)
+                                       continue;
                                if (!displayed_only || row.Displayed) {
                                        int new_height = row.GetPreferredHeight (row.Index, mode, fixedWidth);
 
@@ -3474,6 +3487,9 @@ namespace System.Windows.Forms {
 
                protected virtual void OnCellEnter (DataGridViewCellEventArgs e)
                {
+                       DataGridViewCell cell = GetCellInternal (e.ColumnIndex, e.RowIndex);
+                       cell.OnEnterInternal (e.RowIndex, true);
+
                        DataGridViewCellEventHandler eh = (DataGridViewCellEventHandler)(Events [CellEnterEvent]);
                        if (eh != null)
                                eh (this, e);
@@ -3507,6 +3523,9 @@ namespace System.Windows.Forms {
 
                protected virtual void OnCellLeave (DataGridViewCellEventArgs e)
                {
+                       DataGridViewCell cell = GetCellInternal (e.ColumnIndex, e.RowIndex);
+                       cell.OnLeaveInternal (e.RowIndex, true);
+
                        DataGridViewCellEventHandler eh = (DataGridViewCellEventHandler)(Events [CellLeaveEvent]);
                        if (eh != null)
                                eh (this, e);
@@ -3825,7 +3844,22 @@ namespace System.Windows.Forms {
                                eh (this, e);
                }
 
-               internal void OnColumnRemovedInternal (DataGridViewColumnEventArgs e)
+               internal void OnColumnPreRemovedInternal (DataGridViewColumnEventArgs e)
+               {
+                       if (Columns.Count - 1 == 0) {
+                               MoveCurrentCell (-1, -1, true, false, false, true);
+                               rows.ClearInternal ();
+                       } else if (currentCell != null && CurrentCell.ColumnIndex == e.Column.Index) {
+                               int nextColumnIndex = e.Column.Index;
+                               if (nextColumnIndex >= Columns.Count - 1)
+                                       nextColumnIndex = Columns.Count - 1 - 1;
+                               MoveCurrentCell (nextColumnIndex, currentCell.RowIndex, true, false, false, true);
+                               if (hover_cell != null && hover_cell.ColumnIndex >= e.Column.Index)
+                                       hover_cell = null;
+                       }
+               }
+
+               private void OnColumnPostRemovedInternal (DataGridViewColumnEventArgs e)
                {
                        if (e.Column.CellTemplate != null) {
                                int index = e.Column.Index;
@@ -3835,8 +3869,9 @@ namespace System.Windows.Forms {
                        }
 
                        AutoResizeColumnsInternal ();
-                       OnColumnRemoved (e);
                        PrepareEditingRow (false, true);
+
+                       OnColumnRemoved (e);
                }
 
                protected virtual void OnColumnRemoved (DataGridViewColumnEventArgs e)
@@ -3991,7 +4026,7 @@ namespace System.Windows.Forms {
                        base.OnHandleCreated(e);
                        ReBind ();
                        
-                       if (CurrentCell == null && Rows.Count > 0 && Columns.Count > 0)
+                       if (DataManager == null && CurrentCell == null && Rows.Count > 0 && Columns.Count > 0)
                                MoveCurrentCell (ColumnDisplayIndexToIndex (0), 0, true, false, false, false);
                }
 
@@ -4085,6 +4120,11 @@ namespace System.Windows.Forms {
                protected override void OnMouseDoubleClick (MouseEventArgs e)
                {
                        base.OnMouseDoubleClick(e);
+
+                       HitTestInfo hitInfo = HitTest (e.X, e.Y);
+                       if (hitInfo.Type == DataGridViewHitTestType.Cell)
+                               OnCellMouseDoubleClick (new DataGridViewCellMouseEventArgs (hitInfo.ColumnIndex, hitInfo.RowIndex,
+                                                                                           hitInfo.ColumnX, hitInfo.RowY, e));
                }
 
                private void DoSelectionOnMouseDown (HitTestInfo hitTest)
@@ -4501,6 +4541,14 @@ namespace System.Windows.Forms {
                protected override void OnMouseWheel (MouseEventArgs e)
                {
                        base.OnMouseWheel(e);
+
+                       int delta = SystemInformation.MouseWheelScrollLines * verticalScrollBar.SmallChange;
+                       if (e.Delta < 0)
+                               verticalScrollBar.SafeValueSet (verticalScrollBar.Value + delta);
+                       else
+                               verticalScrollBar.SafeValueSet (verticalScrollBar.Value - delta);
+
+                       OnVScrollBarScroll (this, new ScrollEventArgs (ScrollEventType.ThumbPosition, verticalScrollBar.Value));
                }
 
                protected virtual void OnMultiSelectChanged (EventArgs e)
@@ -4567,8 +4615,8 @@ namespace System.Windows.Forms {
                                bounds.Y += columnHeadersHeight;
                        }
                        
-                       // Reset all columns to !Displayed
-                       for (int i = 0; i < Columns.Count; i++)
+                       // Reset not displayed columns to !Displayed
+                       for (int i = 0; i < first_col_index; i++)
                                Columns[i].DisplayedInternal = false;
                        
                        int gridWidth = rowHeadersVisible ? rowHeadersWidth : 0;
@@ -4586,13 +4634,15 @@ namespace System.Windows.Forms {
                                        break;
                        }
                        
-                       // Reset all rows to !Displayed
-                       for (int i = 0; i < Rows.Count; i++)
+                       // Reset all not displayed rows to !Displayed
+                       for (int i = 0; i < first_row_index; i++)
                                GetRowInternal (i).DisplayedInternal = false;
                        
                        // Draw rows
                        for (int index = first_row_index; index < Rows.Count; index++) {
                                DataGridViewRow row = Rows[index];
+                               if (!row.Visible)
+                                       continue;
                                GetRowInternal (index).DisplayedInternal = true;
        
                                bounds.Height = row.Height;
@@ -4637,7 +4687,8 @@ namespace System.Windows.Forms {
                                        gridWidth += col.Width;
                        
                        foreach (DataGridViewRow row in Rows)
-                               gridHeight += row.Height;
+                               if (row.Visible)
+                                       gridHeight += row.Height;
 
                        if (rowHeadersVisible)
                                gridWidth += rowHeadersWidth;
@@ -4671,7 +4722,7 @@ namespace System.Windows.Forms {
                                        horizontalScrollBar.Minimum = 0;
                                        horizontalScrollBar.Maximum = gridWidth;
                                        horizontalScrollBar.SmallChange = Columns[first_col_index].Width;
-                                       int largeChange = ClientSize.Width - rowHeadersWidth;
+                                       int largeChange = ClientSize.Width - rowHeadersWidth - horizontalScrollBar.Height;
                                        if (largeChange <= 0)
                                                largeChange = ClientSize.Width;
                                        horizontalScrollBar.LargeChange = largeChange;
@@ -4682,7 +4733,7 @@ namespace System.Windows.Forms {
                                        verticalScrollBar.Maximum = gridHeight;
                                        int first_row_height = Rows.Count > 0 ? Rows[Math.Min (Rows.Count - 1, first_row_index)].Height : 0;
                                        verticalScrollBar.SmallChange = first_row_height + 1;
-                                       int largeChange = ClientSize.Height - columnHeadersHeight;
+                                       int largeChange = ClientSize.Height - columnHeadersHeight - verticalScrollBar.Width;
                                        if (largeChange <= 0)
                                                largeChange = ClientSize.Height;
                                        verticalScrollBar.LargeChange = largeChange;
@@ -4855,6 +4906,11 @@ namespace System.Windows.Forms {
                        if (hover_cell != null && hover_cell.RowIndex >= e.RowIndex)
                                hover_cell = null;
 
+                       // Select the first row if we are not databound. 
+                       // If we are databound selection is managed by the data manager.
+                       if (IsHandleCreated && DataManager == null && Rows.Count == 1 && Columns.Count > 0)
+                               MoveCurrentCell (ColumnDisplayIndexToIndex (0), 0, true, false, false, true);
+
                        AutoResizeColumnsInternal ();
                        Invalidate ();
                        OnRowsAdded (e);
@@ -4872,29 +4928,32 @@ namespace System.Windows.Forms {
                        if (eh != null) eh (this, e);
                }
 
-               internal void OnRowsRemovedInternal (DataGridViewRowsRemovedEventArgs e)
+               internal void OnRowsPreRemovedInternal (DataGridViewRowsRemovedEventArgs e)
                {
                        if (selected_rows != null)
                                selected_rows.InternalClear ();
                        if (selected_columns != null)
                                selected_columns.InternalClear ();
 
-                       if (Rows.Count == 0) {
+                       if (Rows.Count - e.RowCount <= 0) {
                                MoveCurrentCell (-1, -1, true, false, false, true);
                                hover_cell = null;
                        } else if (Columns.Count == 0) {
                                MoveCurrentCell (-1, -1, true, false, false, true);
                                hover_cell = null;
-                       } else {
+                       } else if (currentCell != null && currentCell.RowIndex == e.RowIndex) {
                                int nextRowIndex = e.RowIndex;
-                               if (nextRowIndex >= Rows.Count)
-                                       nextRowIndex = Rows.Count - 1;
+                               if (nextRowIndex >= Rows.Count - e.RowCount)
+                                       nextRowIndex = Rows.Count - 1 - e.RowCount;
                                MoveCurrentCell (currentCell != null ? currentCell.ColumnIndex : 0, nextRowIndex, 
                                                 true, false, false, true);
                                if (hover_cell != null && hover_cell.RowIndex >= e.RowIndex)
                                        hover_cell = null;
                        }
+               }
 
+               internal void OnRowsPostRemovedInternal (DataGridViewRowsRemovedEventArgs e)
+               {
                        Invalidate ();
                        OnRowsRemoved (e);
                }
@@ -5605,9 +5664,16 @@ namespace System.Windows.Forms {
                                return;
 
                        int top = 0;
+                       int lastTopVisibleRowIndex = Rows.Count - DisplayedRowCount (false);
+
                        for (int index = 0; index < Rows.Count; index++) {
                                DataGridViewRow row = Rows[index];
-                               if (e.NewValue < top + row.Height) {
+                               if (!row.Visible)
+                                       continue;
+
+                               if (row.Index >= lastTopVisibleRowIndex) {
+                                       first_row_index = lastTopVisibleRowIndex;
+                               } else if (e.NewValue < top + row.Height) {
                                        if (first_row_index != index) {
                                                first_row_index = index;
                                                Invalidate ();
@@ -5620,7 +5686,7 @@ namespace System.Windows.Forms {
                                top += row.Height;
                        }
                        
-                       first_row_index = Rows.Count - DisplayedRowCount (false);
+                       first_row_index = lastTopVisibleRowIndex;
                        Invalidate ();
                        OnScroll (e);
                }
@@ -5635,7 +5701,7 @@ namespace System.Windows.Forms {
                                        OnColumnAddedInternal(new DataGridViewColumnEventArgs(e.Element as DataGridViewColumn));
                                        break;
                                case CollectionChangeAction.Remove:
-                                       OnColumnRemovedInternal(new DataGridViewColumnEventArgs(e.Element as DataGridViewColumn));
+                                       OnColumnPostRemovedInternal(new DataGridViewColumnEventArgs(e.Element as DataGridViewColumn));
                                        break;
                                case CollectionChangeAction.Refresh:
                                        break;
@@ -5771,6 +5837,8 @@ namespace System.Windows.Forms {
                        only_visible = (mode == DataGridViewAutoSizeColumnMode.DisplayedCells || mode == DataGridViewAutoSizeColumnMode.DisplayedCellsExceptHeader);
                        
                        for (int i = first_row; i < Rows.Count; i++) {
+                               if (!Rows[i].Visible)
+                                       continue;
                                if (only_visible) {
                                        Rectangle row_rect = this.GetRowDisplayRectangle (i, false);
                                        if (!ClientRectangle.IntersectsWith (row_rect))
@@ -5939,6 +6007,8 @@ namespace System.Windows.Forms {
                                                // This keeps out things like arrays
                                                if ((typeof(ICollection).IsAssignableFrom (property.PropertyType)))
                                                        continue;
+                                               if (!property.IsBrowsable)
+                                                       continue;
 
                                                if (IsColumnAlreadyBound (property.DisplayName))
                                                        continue;
@@ -5985,6 +6055,34 @@ namespace System.Windows.Forms {
                {
                        if (x == -1 || y == -1)
                                x = y = -1;
+                       else {
+                               if (x < 0 || x > Columns.Count - 1)
+                                       throw new ArgumentOutOfRangeException ("x");
+                               if (y < 0 || y > Rows.Count - 1)
+                                       throw new ArgumentOutOfRangeException ("y");
+
+                               if (!Rows[y].Visible) {
+                                       for (int i = y; i < Rows.Count; i++) {
+                                               if (Rows[i].Visible) {
+                                                       y = i;
+                                                       break;
+                                               }
+                                       }
+                               }
+
+                               if (!Columns[x].Visible) {
+                                       for (int i = x; i < Columns.Count; i++) {
+                                               if (Columns[i].Visible) {
+                                                       x = i;
+                                                       break;
+                                               }
+                                       }
+                               }
+
+                               // in case either no visible columns or rows
+                               if (!Rows[y].Visible || !Columns[x].Visible)
+                                       x = y = -1;
+                       }
 
                        if (!SetCurrentCellAddressCore (x, y, true, false, false)) {
                                ClearSelection ();
@@ -6028,9 +6126,13 @@ namespace System.Windows.Forms {
 
                                        if (disp_x == 0)
                                                delta_x = horizontalScrollBar.Value;
-                                       else
+                                       else {
+                                               // in case the column got removed
+                                               if (first_col_index >= ColumnCount)
+                                                       first_col_index = ColumnCount - 1;
                                                for (int i = disp_x; i < first_col_index; i++)
                                                        delta_x += Columns[ColumnDisplayIndexToIndex (i)].Width;
+                                       }
                                
                                        horizontalScrollBar.SafeValueSet (horizontalScrollBar.Value - delta_x);
                                        OnHScrollBarScroll (this, new ScrollEventArgs (ScrollEventType.ThumbPosition, horizontalScrollBar.Value));
@@ -6046,15 +6148,20 @@ namespace System.Windows.Forms {
 
                                        if (disp_y == 0)
                                                delta_y = verticalScrollBar.Value;
-                                       else
+                                       else {
+                                               // in case the row got removed
+                                               if (first_row_index >= RowCount)
+                                                       first_row_index = RowCount - 1;
                                                for (int i = disp_y; i < first_row_index; i++)
                                                        delta_y += GetRowInternal (i).Height;
+                                       }
 
                                        verticalScrollBar.SafeValueSet (verticalScrollBar.Value - delta_y);
                                        OnVScrollBarScroll (this, new ScrollEventArgs (ScrollEventType.ThumbPosition, verticalScrollBar.Value));
                                } else if (disp_y > first_row_index + displayedRowsCount - 1) {
                                        if (!scrollbarsRefreshed)
                                                RefreshScrollBars ();
+
                                        if (disp_y == Rows.Count - 1)
                                                delta_y = verticalScrollBar.Maximum - verticalScrollBar.Value;
                                        else