mORMot and Open Source friends
Check-in [3492970fc3]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:new OnComponentValidate property to allow custom field content validation
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 3492970fc34cf8bcd87beb5c65cb3ccddcac3935
User & Date: ab 2011-02-16 19:05:17
Context
2011-02-16
19:08
Delphi 2009/2010/XE warning fix check-in: b0e903fbce user: ab tags: trunk
19:05
new OnComponentValidate property to allow custom field content validation check-in: 3492970fc3 user: ab tags: trunk
17:10
new test added check-in: a856fe847c user: ab tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to SQLite3/SQLite3UIEdit.pas.

1
2
3
4
5
6
7
8
9
10
..
55
56
57
58
59
60
61
62



63
64
65
66
67
68
69
..
73
74
75
76
77
78
79







80
81
82
83
84
85
86
...
116
117
118
119
120
121
122

123
124
125
126
127
128
129
...
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150




151
152
153
154
155
156
157
...
458
459
460
461
462
463
464






465
466
467
468
469
470
471
/// Record edition dialog, used to edit record content on the screen
// - this unit is a part of the freeware Synopse SQLite3 database framework,
// licensed under a MPL/GPL/LGPL tri-license; version 1.9.2
unit SQLite3UIEdit;

(*
    This file is part of Synopse SQLite3 database framework.

    Synopse SQLite3 database framework. Copyright (C) 2011 Arnaud Bouchez
      Synopse Informatique - http://synopse.info
................................................................................

  Version 1.9.2
  - handle an optional caption for the window (by default, the caption is
    guessed from the record type)
  - handle display without any associated Client/Model/Ribbon, that is allow
    direct edition of any TSQLRecord child
  - guess the better TGroupBox width on screen for set of enumerates properties
    




*)


interface

uses
................................................................................
  AdvGlowButton, StdCtrls, ExtCtrls;

type
  /// Event used to customize the input component after creation
  TOnComponentCreated = procedure(Obj: TObject; Prop: PPropInfo; Comp: TWinControl) of object;
  /// Event used for the window creation
  TOnComponentCreate = function(Obj: TObject; Prop: PPropInfo; Parent: TWinControl): TWinControl of object;








  /// a common ancestor, used by both TRecordEditForm and TOptionsForm
  TRTTIForm = class(TVistaForm)
  public
    /// this event is used to customize screen text of property names
    OnCaptionName: TOnCaptionName;
    /// this event is used to customize the input components creation
................................................................................
    BtnCancel: TAdvGlowButton;
    Scroll: TScrollBox;
    procedure FormShow(Sender: TObject);
    procedure BtnSaveClick(Sender: TObject);
  protected
    fRec: TSQLRecord;
    fClient: TSQLRestClient;

    // avoid Windows Vista and Seven screen refresh bug (at least with Delphi 7)
    procedure WMUser(var Msg: TMessage); message WM_USER;
  public
    /// create the corresponding components on the dialog for editing a Record
    // - to be used by OnComponentCreate(nil,nil,EditForm) in order
    // to populate the object tree of this Form
    // - create field on the window for all published properties of the
................................................................................
    // dialog window modal apparition on screen
    // - by default, all published fields are displayed, but you can specify
    // a CSV list in the optional CSVFieldNames parameter
    // - editor parameters are taken from the optional Ribbon parameter,
    // and its EditFieldHints/EditExpandFieldHints/EditFieldNameWidth properties
    // - if Ribbon is nil, FieldHints may contain the hints to be displayed on
    // screen (useful if your record is not stored in any TSQLRestClient, but
    // only exists in memory); you can set FieldNamesWidth by hand in this case 
    procedure SetRecord(aClient: TSQLRestClient; aRecord: TSQLRecord;
      CSVFieldNames: PUTF8Char=nil; Ribbon: TSQLRibbon=nil;
      FieldHints: string=''; FieldNamesWidth: integer=0; aCaption: string='');

    /// the associated Record to be edited
    property Rec: TSQLRecord read fRec;
    /// the associated database Client, used to access remote data
    property Client: TSQLRestClient read fClient;




  end;



implementation

{$R *.dfm}
................................................................................
    C := Scroll.Controls[i];
    if not C.Enabled then
      continue; // disabled components didn't modify their value
    FieldIndex := (C.Tag and 255)-1;
    P := Rec.FieldProp(FieldIndex);
    if P=nil then
      continue; // not a value component (label or button)






    if C.InheritsFrom(TSynIntegerLabeledEdit) then
    try
      P^.SetOrdValue(Rec,CNE.Value); // call CNE.GetValue for range checking
    except
      on E: ESynIntegerLabeledEdit do begin // trigerred by CNE.GetValue
        CNE.SetFocus;
        ShowMessage(CNE.EditLabel.Caption+':'#13+E.Message,true);

|







 







|
>
>
>







 







>
>
>
>
>
>
>







 







>







 







|








>
>
>
>







 







>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
..
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
..
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
...
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
...
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
...
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
/// Record edition dialog, used to edit record content on the screen
// - this unit is a part of the freeware Synopse SQLite3 database framework,
// licensed under a MPL/GPL/LGPL tri-license; version 1.13
unit SQLite3UIEdit;

(*
    This file is part of Synopse SQLite3 database framework.

    Synopse SQLite3 database framework. Copyright (C) 2011 Arnaud Bouchez
      Synopse Informatique - http://synopse.info
................................................................................

  Version 1.9.2
  - handle an optional caption for the window (by default, the caption is
    guessed from the record type)
  - handle display without any associated Client/Model/Ribbon, that is allow
    direct edition of any TSQLRecord child
  - guess the better TGroupBox width on screen for set of enumerates properties

  Version 1.13
  - new OnComponentValidate property to allow custom field content validation


*)


interface

uses
................................................................................
  AdvGlowButton, StdCtrls, ExtCtrls;

type
  /// Event used to customize the input component after creation
  TOnComponentCreated = procedure(Obj: TObject; Prop: PPropInfo; Comp: TWinControl) of object;
  /// Event used for the window creation
  TOnComponentCreate = function(Obj: TObject; Prop: PPropInfo; Parent: TWinControl): TWinControl of object;
  /// Event used for individual field validation
  // - must return TRUE if the specified field is correct, FALSE if the content
  // is to be modified
  // - it's up to the handler to inform the user that this field is not correct,
  // via a popup message for instance
  TOnComponentValidate = function(EditControl: TControl; Prop: PPropInfo): boolean of object;


  /// a common ancestor, used by both TRecordEditForm and TOptionsForm
  TRTTIForm = class(TVistaForm)
  public
    /// this event is used to customize screen text of property names
    OnCaptionName: TOnCaptionName;
    /// this event is used to customize the input components creation
................................................................................
    BtnCancel: TAdvGlowButton;
    Scroll: TScrollBox;
    procedure FormShow(Sender: TObject);
    procedure BtnSaveClick(Sender: TObject);
  protected
    fRec: TSQLRecord;
    fClient: TSQLRestClient;
    fOnComponentValidate: TOnComponentValidate;
    // avoid Windows Vista and Seven screen refresh bug (at least with Delphi 7)
    procedure WMUser(var Msg: TMessage); message WM_USER;
  public
    /// create the corresponding components on the dialog for editing a Record
    // - to be used by OnComponentCreate(nil,nil,EditForm) in order
    // to populate the object tree of this Form
    // - create field on the window for all published properties of the
................................................................................
    // dialog window modal apparition on screen
    // - by default, all published fields are displayed, but you can specify
    // a CSV list in the optional CSVFieldNames parameter
    // - editor parameters are taken from the optional Ribbon parameter,
    // and its EditFieldHints/EditExpandFieldHints/EditFieldNameWidth properties
    // - if Ribbon is nil, FieldHints may contain the hints to be displayed on
    // screen (useful if your record is not stored in any TSQLRestClient, but
    // only exists in memory); you can set FieldNamesWidth by hand in this case
    procedure SetRecord(aClient: TSQLRestClient; aRecord: TSQLRecord;
      CSVFieldNames: PUTF8Char=nil; Ribbon: TSQLRibbon=nil;
      FieldHints: string=''; FieldNamesWidth: integer=0; aCaption: string='');

    /// the associated Record to be edited
    property Rec: TSQLRecord read fRec;
    /// the associated database Client, used to access remote data
    property Client: TSQLRestClient read fClient;
    /// event called to check if the content of a field on form is correct
    // - is checked when the user press the "Save" Button
    // - if returns false, component is focused and window is not closed
    property OnComponentValidate: TOnComponentValidate read fOnComponentValidate write fOnComponentValidate;
  end;



implementation

{$R *.dfm}
................................................................................
    C := Scroll.Controls[i];
    if not C.Enabled then
      continue; // disabled components didn't modify their value
    FieldIndex := (C.Tag and 255)-1;
    P := Rec.FieldProp(FieldIndex);
    if P=nil then
      continue; // not a value component (label or button)
    if Assigned(OnComponentValidate) and not OnComponentValidate(C,P) then begin
      // invalid field content -> abort saving
      if C.InheritsFrom(TWinControl) then
        TWinControl(C).SetFocus;
      exit;
    end;
    if C.InheritsFrom(TSynIntegerLabeledEdit) then
    try
      P^.SetOrdValue(Rec,CNE.Value); // call CNE.GetValue for range checking
    except
      on E: ESynIntegerLabeledEdit do begin // trigerred by CNE.GetValue
        CNE.SetFocus;
        ShowMessage(CNE.EditLabel.Caption+':'#13+E.Message,true);

Changes to SynBigTable.pas.

1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
    fText := T.Table['text'];
    if (fText=nil) or not TRTest(T) then exit;
    start(format('%d record text field content update',[n shr 5]));
    for i := 0 to (n shr 5)-1 do begin
      id := i shl 5+1;
      rec := T.RecordGet(id);
      if rec.ID<>id then exit;
      By8[n-id] := IntToStr(id); // as expected by TRTest above
      rec.SetFieldValue(fText,By8[n-id]);
      if not T.RecordUpdate(rec) then exit;
      if rec.GetFieldValue(fText)<>By8[n-id] then exit;
    end;
    fInt := T.Table['int'];
    if (fInt=nil) or not TRTest(T) then exit;
    start(format('%d record Int field content update',[200]));






|







1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
    fText := T.Table['text'];
    if (fText=nil) or not TRTest(T) then exit;
    start(format('%d record text field content update',[n shr 5]));
    for i := 0 to (n shr 5)-1 do begin
      id := i shl 5+1;
      rec := T.RecordGet(id);
      if rec.ID<>id then exit;
      By8[n-id] := Int32ToUTF8(id); // as expected by TRTest above
      rec.SetFieldValue(fText,By8[n-id]);
      if not T.RecordUpdate(rec) then exit;
      if rec.GetFieldValue(fText)<>By8[n-id] then exit;
    end;
    fInt := T.Table['int'];
    if (fInt=nil) or not TRTest(T) then exit;
    start(format('%d record Int field content update',[200]));