View Issue Details

IDProjectCategoryView StatusLast Update
0030061LazarusLCLpublic2016-06-29 14:57
ReporterGabor BorosAssigned ToJesus Reyes 
PrioritynormalSeverityminorReproducibilityN/A
Status closedResolutionfixed 
Product VersionProduct Build 
Target Version1.8Fixed in Version1.7 (SVN) 
Summary0030061: DBGrid - Autosize column with double click on the columns splitter
DescriptionAfter digged into the grids sources found TDBGrid have autosize feature and TCustomGrid have autosize with double click feature. I worked out a solution for myself but with dirty hacks. In my dbgrid override AutoAdjustColumn which contains the modified version of TCustomDBGrid.UpdateAutoSizeColumns and autosize only one column at one time. After this hacked TCustomGrid.DblClick to call AutoAdjustColumn every time if Cursor=crHSplit because TDBGrid not have goDblClickAutoSize option (TCustomDBGrid.Options is TDBGridOptions and TCustomGrid.Options is TGridOptions).

I suggest split TCustomDBGrid.UpdateAutoSizeColumns into parts and make a public TCustomDBGrid.AutoSizeColumn(aCol: Integer). With this can resize one column at one time and can do this from code in runtime. But I not have idea for the option thing which control the autosize at double click.
TagsNo tags attached.
Fixed in Revision52576, 52583
LazTarget1.8
Widgetset
Attached Files
  • dbgrids.pas.patch (4,707 bytes)
    Index: lcl/dbgrids.pas
    ===================================================================
    --- lcl/dbgrids.pas	(revision 52443)
    +++ lcl/dbgrids.pas	(working copy)
    @@ -369,6 +369,7 @@
         procedure ClearSelection(selCurrent:boolean=false);
         function  NeedAutoSizeColumns: boolean;
         procedure RenewColWidths;
    +    procedure Internal_AutoSizeColumn(aCol: Integer; aCanvas: TCanvas; aDatalinkActive: Boolean);
       protected
         procedure AddAutomaticColumns;
         procedure AssignTo(Dest: TPersistent); override;
    @@ -493,6 +494,7 @@
       public
         constructor Create(AOwner: TComponent); override;
         procedure AutoSizeColumns;
    +    procedure AutoSizeColumn(aCol: Integer);
         procedure InitiateAction; override;
         procedure DefaultDrawColumnCell(const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState);
         function  EditorByStyle(Style: TColumnButtonStyle): TWinControl; override;
    @@ -1770,14 +1772,10 @@
     
     procedure TCustomDBGrid.UpdateAutoSizeColumns;
     var
    -  ACol,ARow,w: Integer;
    +  ACol: Integer;
       DatalinkActive: boolean;
       CurActiveRecord: Integer;
    -  Field: TField;
    -  ColWidth: Integer;
       tmpCanvas: TCanvas;
    -  C: TGridColumn;
    -  s: string;
     begin
       if gsAutoSized in GridStatus then
         exit;
    @@ -1790,45 +1788,7 @@
     
       tmpCanvas := GetWorkingCanvas(Canvas);
       try
    -    for aCol:=FixedCols to ColCount-1 do begin
    -
    -      Field := GetFieldFromGridColumn(ACol);
    -      C := ColumnFromGridColumn(ACol);
    -
    -      if (C<>nil) and (C.Title<>nil) then begin
    -        tmpCanvas.Font := C.Title.Font;
    -        ColWidth := tmpCanvas.TextWidth(trim(C.Title.Caption));
    -        tmpCanvas.Font := C.Font;
    -      end else begin
    -        if (Field<>nil) then begin
    -          tmpCanvas.Font := TitleFont;
    -          ColWidth := tmpCanvas.TextWidth(Field.FieldName);
    -        end
    -        else
    -          ColWidth := 0;
    -        tmpCanvas.Font := Font;
    -      end;
    -
    -      if (Field<>nil) and DatalinkActive then
    -        for ARow := FixedRows to RowCount-1 do begin
    -
    -          FDatalink.ActiveRecord := ARow - FixedRows;
    -
    -          if Field.dataType<>ftBlob then
    -            s := trim(Field.DisplayText)
    -          else
    -            s := '(blob)';
    -          w := tmpCanvas.TextWidth(s);
    -          if w>ColWidth then
    -            ColWidth := w;
    -
    -        end;
    -
    -      if ColWidth=0 then
    -        ColWidth := GetColumnWidth(ACol);
    -
    -      ColWidths[ACol] := ColWidth + 15;
    -    end;
    +    for aCol:=FixedCols to ColCount-1 do Internal_AutoSizeColumn(ACol,tmpCanvas,DatalinkActive);
       finally
         if TmpCanvas<>Canvas then
           FreeWorkingCanvas(tmpCanvas);
    @@ -3505,6 +3465,32 @@
       LayoutChanged;
     end;
     
    +procedure TCustomDBGrid.AutoSizeColumn(aCol: Integer);
    +var
    +  DatalinkActive: boolean;
    +  CurActiveRecord: Integer;
    +  tmpCanvas: TCanvas;
    +begin
    +  BeginLayout;
    +
    +  DatalinkActive := FDatalink.Active;
    +  if DatalinkActive then
    +    CurActiveRecord := FDatalink.ActiveRecord;
    +
    +  tmpCanvas := GetWorkingCanvas(Canvas);
    +  try
    +    Internal_AutoSizeColumn(ACol,tmpCanvas,DatalinkActive);
    +  finally
    +    if TmpCanvas<>Canvas then
    +      FreeWorkingCanvas(tmpCanvas);
    +
    +    if DatalinkActive then
    +      FDatalink.ActiveRecord := CurActiveRecord;
    +
    +    EndLayout;
    +  end;
    +end;
    +
     procedure TCustomDBGrid.InitiateAction;
     begin
       {$ifdef dbgDBGrid}DebugLnEnter('%s.InitiateAction INIT', [ClassName]);{$endif}
    @@ -3640,6 +3626,53 @@
       exclude(FGridStatus, gsAutoSized);
     end;
     
    +procedure TCustomDBGrid.Internal_AutoSizeColumn(aCol: Integer; aCanvas: TCanvas; aDatalinkActive: Boolean);
    +var
    +  Field: TField;
    +  C: TGridColumn;
    +  ColWidth: Integer;
    +  ARow,w: Integer;
    +  s: string;
    +
    +begin
    +  Field := GetFieldFromGridColumn(ACol);
    +  C := ColumnFromGridColumn(ACol);
    +
    +  if (C<>nil) and (C.Title<>nil) then begin
    +    aCanvas.Font := C.Title.Font;
    +    ColWidth := aCanvas.TextWidth(trim(C.Title.Caption));
    +    aCanvas.Font := C.Font;
    +  end else begin
    +    if (Field<>nil) then begin
    +      aCanvas.Font := TitleFont;
    +      ColWidth := aCanvas.TextWidth(Field.FieldName);
    +    end
    +    else
    +      ColWidth := 0;
    +    aCanvas.Font := Font;
    +  end;
    +
    +  if (Field<>nil) and aDatalinkActive then
    +    for ARow := FixedRows to RowCount-1 do begin
    +
    +      FDatalink.ActiveRecord := ARow - FixedRows;
    +
    +      if Field.dataType<>ftBlob then
    +        s := trim(Field.DisplayText)
    +      else
    +        s := '(blob)';
    +      w := aCanvas.TextWidth(s);
    +      if w>ColWidth then
    +        ColWidth := w;
    +
    +    end;
    +
    +  if ColWidth=0 then
    +    ColWidth := GetColumnWidth(ACol);
    +
    +  ColWidths[ACol] := ColWidth + 15;
    +end;
    +
     destructor TCustomDBGrid.Destroy;
     begin
       {$ifdef dbgGrid}DebugLn('%s.Destroy', [ClassName]); {$endif}
    
    dbgrids.pas.patch (4,707 bytes)
  • AutoAdjustColumns.png (890 bytes)
    AutoAdjustColumns.png (890 bytes)
  • DBGrid_AutoSize.zip (2,313 bytes)

Activities

Gabor Boros

2016-06-06 11:07

reporter  

dbgrids.pas.patch (4,707 bytes)
Index: lcl/dbgrids.pas
===================================================================
--- lcl/dbgrids.pas	(revision 52443)
+++ lcl/dbgrids.pas	(working copy)
@@ -369,6 +369,7 @@
     procedure ClearSelection(selCurrent:boolean=false);
     function  NeedAutoSizeColumns: boolean;
     procedure RenewColWidths;
+    procedure Internal_AutoSizeColumn(aCol: Integer; aCanvas: TCanvas; aDatalinkActive: Boolean);
   protected
     procedure AddAutomaticColumns;
     procedure AssignTo(Dest: TPersistent); override;
@@ -493,6 +494,7 @@
   public
     constructor Create(AOwner: TComponent); override;
     procedure AutoSizeColumns;
+    procedure AutoSizeColumn(aCol: Integer);
     procedure InitiateAction; override;
     procedure DefaultDrawColumnCell(const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState);
     function  EditorByStyle(Style: TColumnButtonStyle): TWinControl; override;
@@ -1770,14 +1772,10 @@
 
 procedure TCustomDBGrid.UpdateAutoSizeColumns;
 var
-  ACol,ARow,w: Integer;
+  ACol: Integer;
   DatalinkActive: boolean;
   CurActiveRecord: Integer;
-  Field: TField;
-  ColWidth: Integer;
   tmpCanvas: TCanvas;
-  C: TGridColumn;
-  s: string;
 begin
   if gsAutoSized in GridStatus then
     exit;
@@ -1790,45 +1788,7 @@
 
   tmpCanvas := GetWorkingCanvas(Canvas);
   try
-    for aCol:=FixedCols to ColCount-1 do begin
-
-      Field := GetFieldFromGridColumn(ACol);
-      C := ColumnFromGridColumn(ACol);
-
-      if (C<>nil) and (C.Title<>nil) then begin
-        tmpCanvas.Font := C.Title.Font;
-        ColWidth := tmpCanvas.TextWidth(trim(C.Title.Caption));
-        tmpCanvas.Font := C.Font;
-      end else begin
-        if (Field<>nil) then begin
-          tmpCanvas.Font := TitleFont;
-          ColWidth := tmpCanvas.TextWidth(Field.FieldName);
-        end
-        else
-          ColWidth := 0;
-        tmpCanvas.Font := Font;
-      end;
-
-      if (Field<>nil) and DatalinkActive then
-        for ARow := FixedRows to RowCount-1 do begin
-
-          FDatalink.ActiveRecord := ARow - FixedRows;
-
-          if Field.dataType<>ftBlob then
-            s := trim(Field.DisplayText)
-          else
-            s := '(blob)';
-          w := tmpCanvas.TextWidth(s);
-          if w>ColWidth then
-            ColWidth := w;
-
-        end;
-
-      if ColWidth=0 then
-        ColWidth := GetColumnWidth(ACol);
-
-      ColWidths[ACol] := ColWidth + 15;
-    end;
+    for aCol:=FixedCols to ColCount-1 do Internal_AutoSizeColumn(ACol,tmpCanvas,DatalinkActive);
   finally
     if TmpCanvas<>Canvas then
       FreeWorkingCanvas(tmpCanvas);
@@ -3505,6 +3465,32 @@
   LayoutChanged;
 end;
 
+procedure TCustomDBGrid.AutoSizeColumn(aCol: Integer);
+var
+  DatalinkActive: boolean;
+  CurActiveRecord: Integer;
+  tmpCanvas: TCanvas;
+begin
+  BeginLayout;
+
+  DatalinkActive := FDatalink.Active;
+  if DatalinkActive then
+    CurActiveRecord := FDatalink.ActiveRecord;
+
+  tmpCanvas := GetWorkingCanvas(Canvas);
+  try
+    Internal_AutoSizeColumn(ACol,tmpCanvas,DatalinkActive);
+  finally
+    if TmpCanvas<>Canvas then
+      FreeWorkingCanvas(tmpCanvas);
+
+    if DatalinkActive then
+      FDatalink.ActiveRecord := CurActiveRecord;
+
+    EndLayout;
+  end;
+end;
+
 procedure TCustomDBGrid.InitiateAction;
 begin
   {$ifdef dbgDBGrid}DebugLnEnter('%s.InitiateAction INIT', [ClassName]);{$endif}
@@ -3640,6 +3626,53 @@
   exclude(FGridStatus, gsAutoSized);
 end;
 
+procedure TCustomDBGrid.Internal_AutoSizeColumn(aCol: Integer; aCanvas: TCanvas; aDatalinkActive: Boolean);
+var
+  Field: TField;
+  C: TGridColumn;
+  ColWidth: Integer;
+  ARow,w: Integer;
+  s: string;
+
+begin
+  Field := GetFieldFromGridColumn(ACol);
+  C := ColumnFromGridColumn(ACol);
+
+  if (C<>nil) and (C.Title<>nil) then begin
+    aCanvas.Font := C.Title.Font;
+    ColWidth := aCanvas.TextWidth(trim(C.Title.Caption));
+    aCanvas.Font := C.Font;
+  end else begin
+    if (Field<>nil) then begin
+      aCanvas.Font := TitleFont;
+      ColWidth := aCanvas.TextWidth(Field.FieldName);
+    end
+    else
+      ColWidth := 0;
+    aCanvas.Font := Font;
+  end;
+
+  if (Field<>nil) and aDatalinkActive then
+    for ARow := FixedRows to RowCount-1 do begin
+
+      FDatalink.ActiveRecord := ARow - FixedRows;
+
+      if Field.dataType<>ftBlob then
+        s := trim(Field.DisplayText)
+      else
+        s := '(blob)';
+      w := aCanvas.TextWidth(s);
+      if w>ColWidth then
+        ColWidth := w;
+
+    end;
+
+  if ColWidth=0 then
+    ColWidth := GetColumnWidth(ACol);
+
+  ColWidths[ACol] := ColWidth + 15;
+end;
+
 destructor TCustomDBGrid.Destroy;
 begin
   {$ifdef dbgGrid}DebugLn('%s.Destroy', [ClassName]); {$endif}
dbgrids.pas.patch (4,707 bytes)

Gabor Boros

2016-06-06 11:09

reporter   ~0093061

The attached patch contains the above described UpdateAutoSizeColumns splitting and the new public AutoSizeColumn method.

Jesus Reyes

2016-06-23 22:28

developer   ~0093345

Last edited: 2016-06-23 22:30

View 2 revisions

Thanks for the refactoring, I implemented the dgdblClickAutoSize option, so I removed the procedure AutoSizeColumn(aCol: Integer) which I believe you exposed in order to implement the said option. Besides, we don't expose internal properties in dbgrid (like .col or .row) because every cell in dbgrid is addressed with current record and TColumn (and so, to current field).

Please test.

Gabor Boros

2016-06-24 12:30

reporter   ~0093349

DBGrid1.AutoAdjustColumns call give wrong result. (See the attached screenshot.)
"For i:=FixedCols to ColCount"?

Gabor Boros

2016-06-24 12:30

reporter  

AutoAdjustColumns.png (890 bytes)
AutoAdjustColumns.png (890 bytes)

Jesus Reyes

2016-06-24 18:34

developer   ~0093352

Please explain what you think is wrong?

What I see is apparently a screenshot of what would be the columns after AutoSizeColumns was called, nothing new.

I don't understand: "For i:=FixedCols to ColCount"?

Gabor Boros

2016-06-24 20:50

reporter   ~0093355

Sorry for the meaningless description. My problem is every columns (include the first indicator column) resized not just the data columns. Call DBGrid1.AutoAdjustColumns is a wrong idea because AutoSizeColumns exists and do the job? What is the difference between AutoAdjustColumns and AutoSizeColumns?

Jesus Reyes

2016-06-24 22:08

developer   ~0093356

My Appologies, I must be blind as I didn't notice how the indicator column was resized, I will fix that.

About DBGrid1.AutoAdjustColumns and AutoSizeColumns one should disappear, I don't want implement one for calling the other.

Jesus Reyes

2016-06-24 22:57

developer   ~0093357

Exactly, how do you get an widened indicator column?

Please show some code or steps to reproduce that problem.

Gabor Boros

2016-06-25 08:33

reporter  

DBGrid_AutoSize.zip (2,313 bytes)

Gabor Boros

2016-06-25 08:40

reporter   ~0093358

Start the attached example project, click on AutoAdjust, work as expected, close. Start again resize FIELD1 column or FIELD2 column or both columns with the mouse then click on AutoAdjust and see the indicator column resized.

Jesus Reyes

2016-06-25 20:05

developer   ~0093364

Thanks for the example, unfortunately I wasn't able to reproduce the problem.
Any other Information, Idea, configuration, changes, etc. that I need to do in a Lazarus trunk without changes revision in order to reproduce the problem?

Gabor Boros

2016-06-26 00:01

reporter   ~0093365

Windows 10 64bit, FPC 3.0.0 32bit, copy trunk 52577 source to an empty directory, make, start Lazarus, open the attached example, F9, resize a column manually, click on AutoAdjust button.

Jesus Reyes

2016-06-29 03:02

developer   ~0093402

Thanks, fixed.

I didn't delete AutoSizeColumns, it was marked as deprecated for some time, it will be probably delete in 1.8.

Please test.

Gabor Boros

2016-06-29 14:57

reporter   ~0093409

Works form me with trunk 52583 and Windows/Linux-Qt. Thanks!

Issue History

Date Modified Username Field Change
2016-04-26 11:22 Gabor Boros New Issue
2016-04-27 19:13 Jesus Reyes Assigned To => Jesus Reyes
2016-04-27 19:13 Jesus Reyes Status new => assigned
2016-06-06 11:07 Gabor Boros File Added: dbgrids.pas.patch
2016-06-06 11:09 Gabor Boros Note Added: 0093061
2016-06-23 22:28 Jesus Reyes Fixed in Revision => 52576
2016-06-23 22:28 Jesus Reyes LazTarget => 1.8
2016-06-23 22:28 Jesus Reyes Note Added: 0093345
2016-06-23 22:28 Jesus Reyes Status assigned => resolved
2016-06-23 22:28 Jesus Reyes Fixed in Version => 1.7 (SVN)
2016-06-23 22:28 Jesus Reyes Resolution open => fixed
2016-06-23 22:28 Jesus Reyes Target Version => 1.8
2016-06-23 22:30 Jesus Reyes Note Edited: 0093345 View Revisions
2016-06-24 12:30 Gabor Boros Note Added: 0093349
2016-06-24 12:30 Gabor Boros Status resolved => assigned
2016-06-24 12:30 Gabor Boros Resolution fixed => reopened
2016-06-24 12:30 Gabor Boros File Added: AutoAdjustColumns.png
2016-06-24 18:34 Jesus Reyes Note Added: 0093352
2016-06-24 18:34 Jesus Reyes Status assigned => feedback
2016-06-24 20:50 Gabor Boros Note Added: 0093355
2016-06-24 20:50 Gabor Boros Status feedback => assigned
2016-06-24 22:08 Jesus Reyes Note Added: 0093356
2016-06-24 22:57 Jesus Reyes Note Added: 0093357
2016-06-24 22:57 Jesus Reyes Status assigned => feedback
2016-06-25 08:33 Gabor Boros File Added: DBGrid_AutoSize.zip
2016-06-25 08:40 Gabor Boros Note Added: 0093358
2016-06-25 08:40 Gabor Boros Status feedback => assigned
2016-06-25 20:05 Jesus Reyes Note Added: 0093364
2016-06-25 20:05 Jesus Reyes Status assigned => feedback
2016-06-26 00:01 Gabor Boros Note Added: 0093365
2016-06-26 00:01 Gabor Boros Status feedback => assigned
2016-06-29 03:02 Jesus Reyes Fixed in Revision 52576 => 52576, 52583
2016-06-29 03:02 Jesus Reyes Note Added: 0093402
2016-06-29 03:02 Jesus Reyes Status assigned => resolved
2016-06-29 03:02 Jesus Reyes Resolution reopened => fixed
2016-06-29 14:57 Gabor Boros Note Added: 0093409
2016-06-29 14:57 Gabor Boros Status resolved => closed