Recent

Author Topic: Prevent storing of ColWidths of a TCustomDrawGrid descendant  (Read 10151 times)

wp

  • Hero Member
  • *****
  • Posts: 13264
Prevent storing of ColWidths of a TCustomDrawGrid descendant
« on: January 09, 2015, 02:59:46 pm »
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?
« Last Edit: January 09, 2015, 10:43:50 pm by wp »

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Prevent storing of ColWidths of a TCustomDrawGrid descendant
« Reply #1 on: January 09, 2015, 05:11:37 pm »
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

  • Hero Member
  • *****
  • Posts: 13264
Re: Prevent storing of ColWidths of a TCustomDrawGrid descendant
« Reply #2 on: January 09, 2015, 07:01:03 pm »
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

  • Hero Member
  • *****
  • Posts: 3112
Re: Prevent storing of ColWidths of a TCustomDrawGrid descendant
« Reply #3 on: January 09, 2015, 07:53:44 pm »
as far as I know  there is no "UnDefineProperty" method.

You can Override DefineProperties and *not* call inherited.

wp

  • Hero Member
  • *****
  • Posts: 13264
Re: [SOLVED] Prevent storing of ColWidths of a TCustomDrawGrid descendant
« Reply #4 on: January 09, 2015, 10:17:11 pm »
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.
« Last Edit: January 09, 2015, 10:59:05 pm by wp »

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: Prevent storing of ColWidths of a TCustomDrawGrid descendant
« Reply #5 on: January 10, 2015, 12:57:40 am »
No - 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.
« Last Edit: January 10, 2015, 01:05:00 am by engkin »

wp

  • Hero Member
  • *****
  • Posts: 13264
Re: Prevent storing of ColWidths of a TCustomDrawGrid descendant
« Reply #6 on: January 10, 2015, 10:32:58 pm »
Quote
Do 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

  • Hero Member
  • *****
  • Posts: 3112
Re: Prevent storing of ColWidths of a TCustomDrawGrid descendant
« Reply #7 on: January 11, 2015, 12:18:16 am »
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.

BTW: 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

  • Hero Member
  • *****
  • Posts: 13264
Re: Prevent storing of ColWidths of a TCustomDrawGrid descendant
« Reply #8 on: January 11, 2015, 01:03:29 am »
Quote
What 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

  • Hero Member
  • *****
  • Posts: 5643
    • Bart en Mariska's Webstek
Re: Prevent storing of ColWidths of a TCustomDrawGrid descendant
« Reply #9 on: January 11, 2015, 01:12:38 am »
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

  • Hero Member
  • *****
  • Posts: 13264
Re: Prevent storing of ColWidths of a TCustomDrawGrid descendant
« Reply #10 on: January 11, 2015, 01:26:47 am »
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

  • Hero Member
  • *****
  • Posts: 5643
    • Bart en Mariska's Webstek
Re: Prevent storing of ColWidths of a TCustomDrawGrid descendant
« Reply #11 on: January 11, 2015, 01:37:31 am »
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
« Last Edit: January 11, 2015, 02:01:20 am by Bart »

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: Prevent storing of ColWidths of a TCustomDrawGrid descendant
« Reply #12 on: January 11, 2015, 01:47:30 am »
Did you override DefineProperties?

wp

  • Hero Member
  • *****
  • Posts: 13264
Re: Prevent storing of ColWidths of a TCustomDrawGrid descendant
« Reply #13 on: January 11, 2015, 12:59:02 pm »
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 project
  • Add 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.pas
  • Find 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 Lazarus
  • When Lazarus has re-started load "project1" again. Looks like before, and there are ColWidths --> fine
  • Create a new project
  • Add a TStringGrid, doubleclick, enter some text, and modify at least one column width
  • Store 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 again
  • In 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 Lazarus
  • When Lazarus starts again create a new project, add a stringGrid, doubleclick, add some text, change at least one column width
  • Store 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 false
  • Undo all changes of grids.pas
  • In 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 solution
I 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.
« Last Edit: January 11, 2015, 03:01:16 pm by wp »

Bart

  • Hero Member
  • *****
  • Posts: 5643
    • Bart en Mariska's Webstek
Re: Prevent storing of ColWidths of a TCustomDrawGrid descendant
« Reply #14 on: January 11, 2015, 03:16:59 pm »
Please ask Jesus on mailinglist about best approach.

Bart

 

TinyPortal © 2005-2018