View Issue Details

IDProjectCategoryView StatusLast Update
0032329LazarusLCLpublic2017-08-26 21:04
ReporterTony WhymanAssigned ToJesus Reyes 
PrioritynormalSeverityminorReproducibilityalways
Status resolvedResolutionfixed 
Platformx86_64OSLinux MintOS Version18.2
Product Version1.8RC4Product Build 
Target Version1.8Fixed in Version1.9 (SVN) 
Summary0032329: Problems writing a cell editor for a TDBGrid
DescriptionI've been trying to create my own TDBGrid cell editor - actually a TDateTime editor based on TDateEdit and using TStringCellEditor as a template.

The problem is that you cannot replicate TStringCellEditor outside of the Grids unit as it uses the TCustomGrid protected methods "EditorTextChanged" and "EditorIsReadOnly". OK, you can always use a hack to get at a protected method - but you shouldn't have. There seems to be no good reason for these methods to not be public. So I am proposingthat TCustomGrid.EditorTextChanged and TCustomGrid.EditorIsReadOnly are changed to public methods.
Additional InformationDigging Deeper into TDBGrid, you find also that for a cell editor to work, you have to call TCustomGrid.EditorIsReadOnly at least once.

The problem is that TCustomDBGrid overrides EditorIsReadOnly and this override is the only place where FDataLink.Edit is called and it also calls TCustomDBGrid.EditingColumn. In the latter case, if TCustomDBGrid.EditingColumn is not called with argument of "true", then TCustomDBGrid.UpdateData refuses to update the dataset when the cell editor terminates.

In summary without making TCustomGrid.EditorIsReadOnly public, you don't have much hope of writing a cell editor that works with a TDBGrid.
TagsNo tags attached.
Fixed in Revision55745
LazTarget1.8
WidgetsetGTK 2
Attached Files
  • 32329_grids.pas.diff (1,136 bytes)
    Index: grids.pas
    ===================================================================
    --- grids.pas	(revision 55741)
    +++ grids.pas	(working copy)
    @@ -60,6 +60,7 @@
       GM_SETPOS     = LM_INTERFACELAST + 106;
       GM_READY      = LM_INTERFACELAST + 107;
       GM_GETGRID    = LM_INTERFACELAST + 108;
    +  GM_EDITORCHG  = LM_INTERFACELAST + 109;
     
     
     const
    @@ -1062,6 +1063,7 @@
         function  GetTitleShowPrefix(Column: Integer): boolean;
         function  GetPxTopLeft: TPoint;
         function  GetTruncCellHintText(ACol, ARow: Integer): string; virtual;
    +    procedure GM_EditorTextChanged(var Msg: TGridMessage); message GM_EDITORCHG;
         function  GridColumnFromColumnIndex(ColumnIndex: Integer): Integer;
         procedure GridMouseWheel(shift: TShiftState; Delta: Integer); virtual;
         procedure HeaderClick(IsColumn: Boolean; index: Integer); virtual;
    @@ -8308,6 +8310,11 @@
       Result := GetCells(ACol, ARow);
     end;
     
    +procedure TCustomGrid.GM_EditorTextChanged(var Msg: TGridMessage);
    +begin
    +  EditorTextChanged(msg.Col, msg.Row, msg.Value);
    +end;
    +
     function TCustomGrid.GetCells(ACol, ARow: Integer): string;
     begin
       result := '';
    
    32329_grids.pas.diff (1,136 bytes)

Activities

Jesus Reyes

2017-08-25 14:22

developer   ~0102372

If I understood, what you need is to be able to call EditorTextChanged which in turn will call EditorIsReadOnly. I don't think making EditorTextChanged public is a good idea, it should be called in the middle of some editing context which is not obvious just by reading the name.

A possible solution is to call the function through an interface, however we don't use interfaces in the grid for editor implementation so the next solution would be to use a message. Is not as direct as using a simple call but it should work. Please try the attached patch. Call it by dispatching a message crafted with the same information that would be used in the direct call. ej

msg: TGridMessage;
..
msg.lclMsg.msg := GM_EDITORCHG;
msg.row := ..
msg.col := ..
msg.value := text
grid.Dispatch(msg);

Jesus Reyes

2017-08-25 14:23

developer  

32329_grids.pas.diff (1,136 bytes)
Index: grids.pas
===================================================================
--- grids.pas	(revision 55741)
+++ grids.pas	(working copy)
@@ -60,6 +60,7 @@
   GM_SETPOS     = LM_INTERFACELAST + 106;
   GM_READY      = LM_INTERFACELAST + 107;
   GM_GETGRID    = LM_INTERFACELAST + 108;
+  GM_EDITORCHG  = LM_INTERFACELAST + 109;
 
 
 const
@@ -1062,6 +1063,7 @@
     function  GetTitleShowPrefix(Column: Integer): boolean;
     function  GetPxTopLeft: TPoint;
     function  GetTruncCellHintText(ACol, ARow: Integer): string; virtual;
+    procedure GM_EditorTextChanged(var Msg: TGridMessage); message GM_EDITORCHG;
     function  GridColumnFromColumnIndex(ColumnIndex: Integer): Integer;
     procedure GridMouseWheel(shift: TShiftState; Delta: Integer); virtual;
     procedure HeaderClick(IsColumn: Boolean; index: Integer); virtual;
@@ -8308,6 +8310,11 @@
   Result := GetCells(ACol, ARow);
 end;
 
+procedure TCustomGrid.GM_EditorTextChanged(var Msg: TGridMessage);
+begin
+  EditorTextChanged(msg.Col, msg.Row, msg.Value);
+end;
+
 function TCustomGrid.GetCells(ACol, ARow: Integer): string;
 begin
   result := '';
32329_grids.pas.diff (1,136 bytes)

Ondrej Pokorny

2017-08-26 20:41

reporter   ~0102409

I personally don't see a systematic difference in a message and a public method. - IMO the message is just uglier :)

Jesus Reyes

2017-08-26 21:04

developer   ~0102410

If there were currently no exceptions I would go with the message solution, even if it is uglier, but we have already some exceptions, one more would not make a difference. Done.

Issue History

Date Modified Username Field Change
2017-08-24 18:18 Tony Whyman New Issue
2017-08-24 21:36 Jesus Reyes Assigned To => Jesus Reyes
2017-08-24 21:36 Jesus Reyes Status new => assigned
2017-08-25 14:22 Jesus Reyes Note Added: 0102372
2017-08-25 14:23 Jesus Reyes File Added: 32329_grids.pas.diff
2017-08-26 20:41 Ondrej Pokorny Note Added: 0102409
2017-08-26 21:04 Jesus Reyes Fixed in Revision => 55745
2017-08-26 21:04 Jesus Reyes LazTarget => 1.8
2017-08-26 21:04 Jesus Reyes Note Added: 0102410
2017-08-26 21:04 Jesus Reyes Status assigned => resolved
2017-08-26 21:04 Jesus Reyes Fixed in Version => 1.9 (SVN)
2017-08-26 21:04 Jesus Reyes Resolution open => fixed
2017-08-26 21:04 Jesus Reyes Target Version => 1.8