Prevent storing of ColWidths of a TCustomDrawGrid descendant lazarus / 31-LCL ---------------------------------------------------------------------- wp · 2015-01-09 13:59 The package fpspreadsheet_visual implements a grid which is derived from TCustomDrawGrid and displays contents and formats of spreadsheet files. The widths of the grid columns, in particular, are taken from the information stored in the underlying TsWorksheet. Therefore, there is not need to store the ColWidths in the lfm file. The same with the RowHeights. I was trying to avoid this by redeclaring "ColWidths" and "RowHeights" with the attribute "stored false". However, this does not seem to work: after this modification, the ColWidths still show up in the lfm file. The next idea was to modify the streaming mechanism. I see that TCustomGrid has a method "DefineProperties" in which the ColWidths (and RowHeights) actually are prepared for streaming by calling the "DefineProperty" method of the TFiler. But here I am stuck again because - as far as I know  there is no "UnDefineProperty" method. What else can I do to prevent storing colum widths and row heights in the lfm file? ---------------------------------------------------------------------- howardpc · 2015-01-09 16:11 LResources provides a procedure Code: [Select]procedure RegisterPropertyToSkip(PersistentClass: TPersistentClass;   const PropertyName, Note, HelpKeyWord: string);  I've never used it, and am not exactly sure what it does (the LCL help does not have a helpful or informative entry, merely parroting what is obvious from its declaration), but even if it is not directly useful in this case, its source might be useful to you, if it were adapted? ---------------------------------------------------------------------- wp · 2015-01-09 18:01 Found some places in the LCL where it is applied and got the impression that its main purpose is to avoid access to properties in Delphi forms, and less to prevent access to streaming of inherited properties. Nevertheless, I called it in the init section of the worksheetgrid unit, but no effect, ColWidths still there... ---------------------------------------------------------------------- engkin · 2015-01-09 18:53 Quote from: wp on January 09, 2015, 02:59:46 pmas far as I know  there is no "UnDefineProperty" method. You can Override DefineProperties and *not* call inherited. ---------------------------------------------------------------------- wp · 2015-01-09 21:17 Excellent. Ancestors does not define properties! [EDIT] No - now old forms are broken because the property "ColWidths" does not exist any more... I think I'll propose a patch for TCustomGrid in which the property "ColWidths" is declared with the modifier "stored IsColWidthsStored", and "IsColWidthsStored" is a virtual function returning true by default, but false for TsWorksheetGrid. ---------------------------------------------------------------------- engkin · 2015-01-09 23:57 Quote from: wp on January 09, 2015, 10:17:11 pmNo - now old forms are broken because the property "ColWidths" does not exist any more... Do you need them, if not delete them from the lfm files. Edit: Forgot to say, you can decide to call inherited or not to read these properties by applying your idea about IsColWidthsStored in your own DefineProperties. ---------------------------------------------------------------------- wp · 2015-01-10 21:32 QuoteDo you need them, if not delete them from the lfm files.The users of fpspreadsheet would be very "happy" if they had to manually edit existing lfm files because of a minor cosmetic change. BTW: After introducing the proposed "stored" attribute approach, ColWidths are still written to the lfm. The streaming mechanism of grids is still kind of mysterious to me... ---------------------------------------------------------------------- engkin · 2015-01-10 23:18 1-The old forms have ColWidths. 2-Your updated control does not *write* ColWidths. 3-Your updated control does not care to read them if they exist. 4-Your updated control will not complain if they do exist. 5-Users with old forms will *not* have a problem when they upgrade. 6-Users that updated their forms will have a problem if they downgrade. <-- This is normal. If I open an old form in Lazarus with updated control and saved it, I will have a "new form" without ColWidths. Now, if I open this new form in Lazarus with older version of your control, it *will* complain about ColWidths. <-- This is normal. Quote from: wp on January 10, 2015, 10:32:58 pmBTW: After introducing the proposed "stored" attribute approach, ColWidths are still written to the lfm. What you have after stored is returning "True", always. Check, for instance, BiDiMode property. Code: [Select]    property BiDiMode: TBiDiMode read FBiDiMode write SetBiDiMode stored IsBiDiModeStored default bdLeftToRight; ... function TControl.IsBiDiModeStored: boolean; begin   Result := not ParentBidiMode; end; ---------------------------------------------------------------------- wp · 2015-01-11 00:03 QuoteWhat you have after stored is returning "True", always. Sorry I don't catch what you are trying to say. I agree with every other sentence, that's what I would expect. But the behavior is different. According to a proposal by Bart in my bugtracker report (http://bugs.freepascal.org/view.php?id=27279) I am having now: Code: [Select]type   TsCustomWorksheetGrid = class(TCustomDrawGrid)   ...   protected     property WorkbookSource: TsWorkbookSource ...  // links to the spreadsheet file containing the colwidths   public     property ColWidths stored false;     ...   end;   TsWorksheetGrid = class(TsCustomWorksheetGrid)     ...   published     property WorkbookSource;   end;   ...   // no modification in grids.pas (1) I installed the package with this component (2) New project, add a TsWorksheetGrid  and a TsWorkbookSource. (3) Link the WorksheetGrid.WorkbookSource to the TsWorkbookSource to get the default column widths. (4) Save (5) When I look at the lfm file there are ColWidths - against expectation. (And there is an Access violation, but maybe this could be related to some of my dependent code.) ---------------------------------------------------------------------- Bart · 2015-01-11 00:12 TsWorksheetGrid = class(TsCustomWorksheetGrid) This class publishes the ColWidhts itself. If you don't want them in lfm, why publish them in the first place? It makes no sense to me at all. Bart ---------------------------------------------------------------------- wp · 2015-01-11 00:26 You lost me: I never "published" ColWidths, in above example they are "public"... In fact, they should be "protected" as inherited from TCustomGrid, but if I put them into "protected" they still appear in the lfm file. ---------------------------------------------------------------------- Bart · 2015-01-11 00:37 Maybe override the stream reader functions? Code: [Select]procedure TxxxGrid.ReadColWidths(Reader: TReader); var   i: integer; begin   with Reader do begin     ReadListBegin;     for i:=0 to ColCount-1 do       {ColWidths[I] :=} ReadInteger;  //just read, do not apply     ReadListEnd;   end; end; (Needs the ReadColWidths to be protected and virtual in TCustomGrid) Or make NeedWidths a virtual function of TCustomGrid instead of a local function inside DefineProperties and simply let it return False? Or override the setter for ColWidths maybe? I would ask Jesus. Bart ---------------------------------------------------------------------- engkin · 2015-01-11 00:47 Did you override DefineProperties? ---------------------------------------------------------------------- wp · 2015-01-11 11:59 Here an example how you can see what I am doing. You don't need fpspreadsheet, just use the standard TStringGrid for it, but you should make a backup copy of grids.pas (in folder (lazarus)\lcl). Original StringGrid to test backward compatiblity: Create a new projectAdd a TStringGrid, doubleclick and enter some text and modify at least one column width.Store as "project1"/"unit1"Look at lfm file -> there are ColWidths, as expected.Make StringGrid's ColWidths "stored false": Load grids.pasFind the TCustomGrid line "property ColWidths[..." and add "stored false", i.e. it should read now Code: [Select] property ColWidths[ACol: Integer]: Integer read GetColWidths write SetColWidths stored false; Recompile LazarusWhen Lazarus has re-started load "project1" again. Looks like before, and there are ColWidths --> fineCreate a new projectAdd a TStringGrid, doubleclick, enter some text, and modify at least one column widthStore as "project2"/"unit2" Look at the lfm file --> there are ColWidths! They should not be there because of the "stored false" attribute.Modifying DefineProperties way as Engkin suggests Open grids againIn TCustomStringGrid seek the implementation of "DefineProperties". Comment the line "inherited...": The DefineProperties inherited from TCustomGrid do store the column widths (the ancestors of TCustomGrid don't do anything here, so we can skip the "inherited" without losing anything). The entire procedure should be like this:Code: [Select]procedure TCustomStringGrid.DefineProperties(Filer: TFiler); begin   //inherited DefineProperties(Filer);   DefineCellsProperty(Filer); end; Recompile LazarusWhen Lazarus starts again create a new project, add a stringGrid, doubleclick, add some text, change at least one column widthStore as "project3"/"unit3"Look at lfm file --> There are NO ColWidths --> fine!Open old project1 which was created with the original version of TStringGrid  --> Stream-Read Error "No property ColWidths". This means that the new version is not backward compatible - I absolutely want to avoid this.Bart's idea of local function "NeedWidths" (within "DefineProperties") returning falseUndo all changes of grids.pasIn grids.pas find "TCustomGrid.DefineProperties". Replace the parameter "NeedWidths" of the first call to "Filer.DefineProperty" by "false"Rebuild Lazarus.Load project 1 -> no streaming error. Looks like with original stringGrid.Create a new project with a TStringGrid, change at least one colum width. Save as "project4"/"unit4".Look at lfm --> no ColWidths. ==> This seems to be the solutionI am preparing a new patch for my bug report. The patch will make NeedWidths and NeedHeights protected virtual functions of TCustomGrid. Inherited grids not needing ColWidhts/RowHeights can return false. ---------------------------------------------------------------------- Bart · 2015-01-11 14:16 Please ask Jesus on mailinglist about best approach. Bart ---------------------------------------------------------------------- engkin · 2015-01-12 03:30 Quote from: wp on January 11, 2015, 12:59:02 pmOpen old project1 which was created with the original version of TStringGrid  --> Stream-Read Error "No property ColWidths". This means that the new version is not backward compatible - I absolutely want to avoid this. You can instruct the reader not to complain by calling RegisterPropertyToSkip. In your example of TStringGrid add to the end of Grids.pas: Code: [Select]... initialization   RegisterPropertyToSkip(TStringGrid, 'ColWidths', 'Mention the reason you removed this property',''); end. Recompile Lazarus Open old project1 which was created with the original version of TStringGrid  --> No problem! This same method was used in TAChartAxis: Code: [Select]procedure SkipObsoleteAxisProperties; const   TRANSFORM_NOTE = 'Obsolete, use Transformations instead'; begin   RegisterPropertyToSkip(TChartAxis, 'Offset', TRANSFORM_NOTE, '');   RegisterPropertyToSkip(TChartAxis, 'Scale', TRANSFORM_NOTE, '');   RegisterPropertyToSkip(TChartAxis, 'Transformation', TRANSFORM_NOTE, ''); end; ... initialization ...   SkipObsoleteAxisProperties; ---------------------------------------------------------------------- wp · 2015-01-12 11:43 Thanks, engkin. Works perfectly. I used your solution in fpspreadsheet now since it is not dependent on a modification of grids.pas. ---------------------------------------------------------------------- Bart · 2015-01-12 12:43 I changed the resolution of the bugreport to: no change required. Bart