The initial layout of the datagrid (CalcGridAreas in particular) ends up
recursively calling itself (on one test it was being invoked 5 or 6
times.) You can see this happening with a large datagrid by watching
the vertical scrollbar's slider change size as it lays out.
This patch calculates the layout/positioning of everything in a single
pass, which speeds things up quite a bit.
Chris
Index: System.Windows.Forms/ChangeLog
===================================================================
--- System.Windows.Forms/ChangeLog (revision 60602)
+++ System.Windows.Forms/ChangeLog (working copy)
@@ -1,3 +1,11 @@
+2006-05-11 Chris Toshok <[EMAIL PROTECTED]>
+
+ * DataGridDrawingLogic.cs: make CalcGridAreas non-reentrant.
+ Figure out the positioning/layout in a single pass instead of
+ multiple recursive invocations. Speeds up the initial display of
+ the data grid. Also, make many things private that were
+ originally public but unused outside this class.
+
2006-05-11 Atsushi Enomoto <[EMAIL PROTECTED]>
* TextBoxBase.cs : implement CTRL+A (select all). Fixed bug #78368.
Index: System.Windows.Forms/DataGridDrawingLogic.cs
===================================================================
--- System.Windows.Forms/DataGridDrawingLogic.cs (revision 60602)
+++ System.Windows.Forms/DataGridDrawingLogic.cs (working copy)
@@ -71,7 +71,7 @@
}
// Gets a column from a pixel
- public int FromPixelToColumn (int pixel)
+ private int FromPixelToColumn (int pixel)
{
int width = 0;
int cnt = grid.CurrentTableStyle.GridColumnStyles.Count;
@@ -129,51 +129,106 @@
}
}
+ bool in_calc_grid_areas;
public void CalcGridAreas ()
{
if (grid.IsHandleCreated == false) // Delay calculations until the handle is created
return;
+ /* make sure we don't happen to end up in this method again */
+ if (in_calc_grid_areas)
+ return;
+
+ in_calc_grid_areas = true;
+
/* Order is important. E.g. row headers max. height depends on caption */
grid.horz_pixeloffset = 0;
CalcCaption ();
CalcParentRows ();
- CalcRowsHeaders ();
+ CalcRowsHeaders (grid.visiblerow_count);
CalcColumnsHeader ();
CalcCellsArea ();
- UpdateVisibleRowCount (); // need it to be able to calcultate the need of horz scrollbar
- if (SetUpVerticalScrollBar ()) { // We need a Vertical ScrollBar
-
+ bool needHoriz = false;
+ bool needVert = false;
+
+ /* figure out which scrollbars we need, and what the visible areas are */
+ int visible_row_count;
+ int visible_cells_width = cells_area.Width;
+ int visible_cells_height = cells_area.Height;
+ int width_of_all_columns = CalcAllColumnsWidth ();
+ int allrows = grid.RowsCount;
+ if (grid.ShowEditRow && grid.RowsCount > 0)
+ allrows++;
+
+ /* use a loop to iteratively calculate whether
+ * we need horiz/vert scrollbars. */
+ for (int i = 0; i < 2; i ++) {
+ if (needVert)
+ visible_cells_width = cells_area.Width - grid.vert_scrollbar.Width;
+ if (needHoriz)
+ visible_cells_height = cells_area.Height - grid.horiz_scrollbar.Height;
+ visible_row_count = GetVisibleRowCount (visible_cells_height);
+
+ needHoriz = (width_of_all_columns > visible_cells_width);
+ needVert = (visible_row_count != allrows);
+ }
+
+ int horiz_scrollbar_width = grid.ClientRectangle.Width;
+ int horiz_scrollbar_maximum = 0;
+ int vert_scrollbar_height = 0;
+ int vert_scrollbar_maximum = 0;
+
+ if (needVert)
+ SetUpVerticalScrollBar (out vert_scrollbar_height, out vert_scrollbar_maximum);
+
+ if (needHoriz)
+ SetUpHorizontalScrollBar (out horiz_scrollbar_maximum);
+
+ cells_area.Width = visible_cells_width;
+ cells_area.Height = visible_cells_height;
+
+ if (needVert && needHoriz) {
if (grid.ShowParentRowsVisible) {
parent_rows.Width -= grid.vert_scrollbar.Width;
}
- if (grid.columnheaders_visible == false || grid.CurrentTableStyle.GridColumnStyles.Count == 0) {
+ if (!ShowingColumnHeaders) {
if (columnshdrs_area.X + columnshdrs_area.Width > grid.vert_scrollbar.Location.X) {
columnshdrs_area.Width -= grid.vert_scrollbar.Width;
}
}
- if (cells_area.X + cells_area.Width >= grid.vert_scrollbar.Location.X) {
- cells_area.Width -= grid.vert_scrollbar.Width;
- }
+ horiz_scrollbar_width -= grid.vert_scrollbar.Width;
+ vert_scrollbar_height -= grid.horiz_scrollbar.Height;
}
- if (SetUpHorizontalScrollBar ()) { // We need a Horizontal ScrollBar
- cells_area.Height -= grid.horiz_scrollbar.Height;
-
+ if (needVert) {
if (rowshdrs_area.Y + rowshdrs_area.Height > grid.ClientRectangle.Y + grid.ClientRectangle.Height) {
rowshdrs_area.Height -= grid.horiz_scrollbar.Height;
rowshdrs_maxheight -= grid.horiz_scrollbar.Height;
}
+
+ grid.vert_scrollbar.Height = vert_scrollbar_height;
+ grid.vert_scrollbar.Maximum = vert_scrollbar_maximum;
+ grid.Controls.Add (grid.vert_scrollbar);
+ grid.vert_scrollbar.Visible = true;
}
+ else {
+ grid.Controls.Remove (grid.vert_scrollbar);
+ grid.vert_scrollbar.Visible = false;
+ }
- // Reajust scrollbars to avoid overlapping at the corners
- if (grid.vert_scrollbar.Visible && grid.horiz_scrollbar.Visible) {
- grid.horiz_scrollbar.Width -= grid.vert_scrollbar.Width;
- grid.vert_scrollbar.Height -= grid.horiz_scrollbar.Height;
+ if (needHoriz) {
+ grid.horiz_scrollbar.Width = horiz_scrollbar_width;
+ grid.horiz_scrollbar.Maximum = horiz_scrollbar_maximum;
+ grid.Controls.Add (grid.horiz_scrollbar);
+ grid.horiz_scrollbar.Visible = true;
}
+ else {
+ grid.Controls.Remove (grid.horiz_scrollbar);
+ grid.horiz_scrollbar.Visible = false;
+ }
UpdateVisibleColumn ();
UpdateVisibleRowCount ();
@@ -183,9 +238,11 @@
//Console.WriteLine ("DataGridDrawing.CalcGridAreas rowshdrs_area:{0}", rowshdrs_area);
//Console.WriteLine ("DataGridDrawing.CalcGridAreas columnshdrs_area:{0}", columnshdrs_area);
//Console.WriteLine ("DataGridDrawing.CalcGridAreas cells:{0}", cells_area);
+
+ in_calc_grid_areas = false;
}
- public void CalcCaption ()
+ private void CalcCaption ()
{
if (grid.caption_visible == false) {
caption_area = Rectangle.Empty;
@@ -200,7 +257,7 @@
//Console.WriteLine ("DataGridDrawing.CalcCaption {0}", caption_area);
}
- public void CalcCellsArea ()
+ private void CalcCellsArea ()
{
if (grid.caption_visible) {
cells_area.Y = caption_area.Y + caption_area.Height;
@@ -212,7 +269,7 @@
cells_area.Y += parent_rows.Height;
}
- if (!(grid.columnheaders_visible == false || grid.CurrentTableStyle.GridColumnStyles.Count == 0)) {
+ if (ShowingColumnHeaders) {
cells_area.Y += columnshdrs_area.Height;
}
@@ -223,11 +280,11 @@
//Console.WriteLine ("DataGridDrawing.CalcCellsArea {0}", cells_area);
}
- public void CalcColumnsHeader ()
+ private void CalcColumnsHeader ()
{
int width_all_cols, max_width_cols;
- if (grid.columnheaders_visible == false || grid.CurrentTableStyle.GridColumnStyles.Count == 0) {
+ if (!ShowingColumnHeaders) {
columnshdrs_area = Rectangle.Empty;
return;
}
@@ -267,7 +324,7 @@
//Console.WriteLine ("DataGridDrawing.CalcColumnsHeader {0}", columnshdrs_area);
}
- public void CalcParentRows ()
+ private void CalcParentRows ()
{
if (grid.ShowParentRowsVisible == false) {
parent_rows = Rectangle.Empty;
@@ -288,7 +345,7 @@
//Console.WriteLine ("DataGridDrawing.CalcParentRows {0}", parent_rows);
}
- public void CalcRowsHeaders ()
+ private void CalcRowsHeaders (int visiblerow_count)
{
if (grid.CurrentTableStyle.CurrentRowHeadersVisible == false) {
rowshdrs_area = Rectangle.Empty;
@@ -305,19 +362,49 @@
rowshdrs_area.Y += parent_rows.Height;
}
- if (!(grid.columnheaders_visible == false || grid.CurrentTableStyle.GridColumnStyles.Count == 0)) { // first block is painted by ColumnHeader
+ if (ShowingColumnHeaders) { // first block is painted by ColumnHeader
rowshdrs_area.Y += ColumnsHeaderHeight;
}
rowshdrs_area.X = grid.ClientRectangle.X;
rowshdrs_area.Width = grid.RowHeaderWidth;
- rowshdrs_area.Height = grid.visiblerow_count * grid.RowHeight;
+ rowshdrs_area.Height = visiblerow_count * grid.RowHeight;
rowshdrs_maxheight = grid.ClientRectangle.Height + grid.ClientRectangle.Y - rowshdrs_area.Y;
//Console.WriteLine ("DataGridDrawing.CalcRowsHeaders {0} {1}", rowshdrs_area,
// rowshdrs_maxheight);
}
+ private int GetVisibleRowCount (int visibleHeight)
+ {
+ int rv;
+ int total_rows = grid.RowsCount;
+
+ if (grid.ShowEditRow && grid.RowsCount > 0) {
+ total_rows++;
+ }
+
+ int rows_height = (total_rows - grid.first_visiblerow) * grid.RowHeight;
+ int max_rows = visibleHeight / grid.RowHeight;
+
+ if (max_rows > total_rows) {
+ max_rows = total_rows;
+ }
+
+ if (rows_height > cells_area.Height) {
+ rv = max_rows;
+ } else {
+ rv = total_rows;
+ }
+
+ CalcRowsHeaders (rv); // Height depends on num of visible rows
+
+ if (rv + grid.first_visiblerow > total_rows)
+ rv = total_rows - grid.first_visiblerow;
+
+ return rv;
+ }
+
public void UpdateVisibleColumn ()
{
if (grid.CurrentTableStyle.GridColumnStyles.Count == 0) {
@@ -341,30 +428,20 @@
public void UpdateVisibleRowCount ()
{
int max_height = cells_area.Height;
+ int max_rows = max_height / grid.RowHeight;
+
int total_rows = grid.RowsCount;
if (grid.ShowEditRow && grid.RowsCount > 0) {
total_rows++;
}
- int rows_height = (total_rows - grid.first_visiblerow) * grid.RowHeight;
- int max_rows = max_height / grid.RowHeight;
-
if (max_rows > total_rows) {
max_rows = total_rows;
}
- if (rows_height > cells_area.Height) {
- grid.visiblerow_count = max_rows;
- } else {
- grid.visiblerow_count = total_rows;
- }
+ grid.visiblerow_count = GetVisibleRowCount (max_height);
- CalcRowsHeaders (); // Height depends on num of visible rows
-
- if (grid.visiblerow_count + grid.first_visiblerow > total_rows)
- grid.visiblerow_count = total_rows - grid.first_visiblerow;
-
if (grid.visiblerow_count < max_rows) {
grid.visiblerow_count = max_rows;
grid.first_visiblerow = total_rows - max_rows;
@@ -468,8 +545,11 @@
Rectangle rect_row = new Rectangle ();
+ int row_width = CalcAllColumnsWidth ();
+ if (row_width > cells_area.Width)
+ row_width = cells_area.Width;
rect_row.X = cells_area.X;
- rect_row.Width = cells_area.Width;
+ rect_row.Width = row_width;
rect_row.Height = grid.RowHeight;
rect_row.Y = cells_area.Y + ((row - grid.FirstVisibleRow) * grid.RowHeight);
grid.Invalidate (rect_row);
@@ -504,47 +584,25 @@
rect_col.Height = cells_area.Height;
grid.Invalidate (rect_col);
}
-
- // Return true if the scrollbar is needed
- public bool SetUpHorizontalScrollBar ()
+
+ void SetUpHorizontalScrollBar (out int maximum)
{
- int width_all = CalcAllColumnsWidth ();
+ maximum = CalcAllColumnsWidth ();
- if (width_all <= cells_area.Width) {
- grid.horiz_scrollbar.Visible = false;
- grid.Controls.Remove (grid.horiz_scrollbar);
- return false;
- }
-
grid.horiz_scrollbar.Location = new Point (grid.ClientRectangle.X, grid.ClientRectangle.Y +
grid.ClientRectangle.Height - grid.horiz_scrollbar.Height);
grid.horiz_scrollbar.Size = new Size (grid.ClientRectangle.Width,
grid.horiz_scrollbar.Height);
- grid.horiz_scrollbar.Maximum = width_all;// - cells_area.Width;
grid.horiz_scrollbar.LargeChange = cells_area.Width;
- grid.Controls.Add (grid.horiz_scrollbar);
- grid.horiz_scrollbar.Visible = true;
- return true;
}
- // Return true if the scrollbar is needed
- public bool SetUpVerticalScrollBar ()
+
+ void SetUpVerticalScrollBar (out int height, out int maximum)
{
- int y, height;
- int allrows = grid.RowsCount;
-
- if (grid.ShowEditRow && grid.RowsCount > 0) {
- allrows++;
- }
+ int y;
- if (grid.visiblerow_count == allrows) {
- grid.vert_scrollbar.Visible = false;
- grid.Controls.Remove (grid.vert_scrollbar);
- return false;
- }
-
if (grid.caption_visible) {
y = grid.ClientRectangle.Y + caption_area.Height;
height = grid.ClientRectangle.Height - caption_area.Height;
@@ -559,17 +617,13 @@
grid.vert_scrollbar.Size = new Size (grid.vert_scrollbar.Width,
height);
- grid.vert_scrollbar.Maximum = grid.RowsCount;
+ maximum = grid.RowsCount;
if (grid.ShowEditRow && grid.RowsCount > 0) {
- grid.vert_scrollbar.Maximum++;
+ maximum++;
}
grid.vert_scrollbar.LargeChange = VLargeChange;
-
- grid.Controls.Add (grid.vert_scrollbar);
- grid.vert_scrollbar.Visible = true;
- return true;
}
#endregion // Public Instance Methods
@@ -594,7 +648,11 @@
}
}
- public int ColumnsHeaderHeight {
+ bool ShowingColumnHeaders {
+ get { return grid.columnheaders_visible == false || grid.CurrentTableStyle.GridColumnStyles.Count == 0; }
+ }
+
+ int ColumnsHeaderHeight {
get {
return grid.CurrentTableStyle.HeaderFont.Height + 6;
}
_______________________________________________
Mono-winforms-list maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-winforms-list