fpdatasetform.pp 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184
  1. {
  2. $Id: header,v 1.1 2000/07/13 06:33:45 michael Exp $
  3. This file is part of the Free Component Library (FCL)
  4. Copyright (c) 1999-2000 by the Free Pascal development team
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. unit fpdatasetform;
  12. {$mode objfpc}{$H+}
  13. interface
  14. uses
  15. Classes, SysUtils, fphtml, htmldefs, htmlwriter, db, htmlelements;
  16. type
  17. THTMLDatasetFormProducer = class;
  18. TFormFieldItem = class;
  19. TFormButtonItem = class;
  20. TFieldCellEvent = procedure (Sender:THTMLDatasetFormProducer; FieldDef:TFormFieldItem;
  21. IsLabel:boolean; Cell : THTMLCustomelement) of object;
  22. TButtonEvent = procedure (Sender:THTMLDatasetFormProducer; ButtonDef:TFormButtonItem;
  23. Button : THTML_button) of object;
  24. TProducerEvent = procedure (Sender:THTMLDatasetFormProducer; FieldDef:TFormFieldItem;
  25. Producer:THTMLContentProducer) of object;
  26. THTMLElementEvent = procedure (Sender:THTMLDatasetFormProducer; element : THTMLCustomElement) of object;
  27. TFieldCheckEvent = procedure (aField:TField; var check:boolean) of object;
  28. TFormInputType = (fittext,fitpassword,fitcheckbox,fitradio,fitfile,fithidden,
  29. fitproducer,fittextarea,fitrecordselection);
  30. { TTablePosition }
  31. TTablePosition = class (TPersistent)
  32. private
  33. FAlignHor: THTMLalign;
  34. FAlignVer: THTMLvalign;
  35. FColSpan: integer;
  36. FLeft: integer;
  37. FRowSpan: integer;
  38. FTop: integer;
  39. protected
  40. procedure AssignTo(Dest: TPersistent); override;
  41. public
  42. constructor create;
  43. published
  44. property Left : integer read FLeft write FLeft;
  45. property Top : integer read FTop write FTop;
  46. property ColSpan : integer read FColSpan write FColSpan default 1;
  47. property RowSpan : integer read FRowSpan write FRowSpan default 1;
  48. property AlignVertical : THTMLvalign read FAlignVer write FAlignVer default vaEmpty;
  49. property AlignHorizontal : THTMLalign read FAlignHor write FAlignHor default alEmpty;
  50. end;
  51. { TFormFieldItem }
  52. TFormFieldItem = class (TCollectionItem)
  53. private
  54. FAction: string;
  55. FField: TField;
  56. FFieldName: string;
  57. FInputType: TFormInputType;
  58. FLabelCaption: string;
  59. FLabelAbove : boolean;
  60. FLabelPos: TTablePosition;
  61. FProducer: THTMLContentProducer;
  62. FValuePos: TTablePosition;
  63. procedure SetLabelPos(const AValue: TTablePosition);
  64. procedure SetValuePos(const AValue: TTablePosition);
  65. protected
  66. procedure AssignTo(Dest: TPersistent); override;
  67. public
  68. constructor Create(ACollection: TCollection); override;
  69. destructor Destroy; override;
  70. property Field : TField read FField;
  71. published
  72. property Fieldname : string read FFieldName write FFieldname;
  73. // the field to show/edit
  74. property LabelCaption : string read FLabelCaption write FLabelCaption;
  75. // the text to show for the control
  76. property LabelPos : TTablePosition read FLabelPos write SetLabelPos;
  77. // place of the label in the table-grid
  78. property LabelAbove : boolean read FLabelAbove write FLabelAbove default false;
  79. // if not SeparateLabel then place a <BR> between label and edit/value
  80. property ValuePos : TTablePosition read FValuePos write SetValuePos;
  81. // place of the value in the table-grid
  82. { only when editting: }
  83. property InputType : TFormInputType read FInputType write FInputType default fittext;
  84. // the type of form control to use
  85. property Producer : THTMLContentProducer read FProducer write FProducer;
  86. // the producer to include when generating the value
  87. { only when showing: }
  88. property Action : string read FAction write FAction;
  89. // the link to include in the value
  90. end;
  91. { TFormFieldCollection }
  92. TFormFieldCollection = class (TCollection)
  93. private
  94. function GetItem(index : integer): TFormFieldItem;
  95. procedure SetItem(index : integer; const AValue: TFormFieldItem);
  96. public
  97. constructor create;
  98. function AddField (afieldname, acaption : string) : TFormFieldItem;
  99. property Items [index : integer] : TFormFieldItem read GetItem write SetItem;
  100. end;
  101. TFormButtonType = (fbtSubmit, fbtReset, fbtPushbutton);
  102. TImagePlace = (ipOnly, ipBefore, ipAfter, ipUnder, ipAbove);
  103. { TFormButtonItem }
  104. TFormButtonItem = class (TCollectionItem)
  105. private
  106. FButtonType: TFormButtonType;
  107. FCaption: string;
  108. FImage: string;
  109. FName: string;
  110. FImagePlace: TImagePlace;
  111. FValue: string;
  112. protected
  113. procedure AssignTo(Dest: TPersistent); override;
  114. public
  115. constructor create (ACollection : TCollection); override;
  116. published
  117. property Name : string read FName write FName;
  118. property Value : string read FValue write FValue;
  119. property Caption : string read FCaption write FCaption;
  120. // Text on button, or as hint with image
  121. property Image : string read FImage write FImage;
  122. // Image to show on the button
  123. property ImagePlace : TImagePlace read FImagePlace write FImagePlace;
  124. // where the image is placed regarding from the caption.
  125. // if ipOnly; the caption is placed in the alternate text of the image (hint)
  126. property ButtonType : TFormButtonType read FButtonType write FButtonType default fbtPushButton;
  127. // Where the button is used for
  128. end;
  129. { TFormButtonCollection }
  130. TFormButtonCollection = class (TCollection)
  131. private
  132. function GetItem(index : integer): TFormButtonItem;
  133. procedure SetItem(index : integer; const AValue: TFormButtonItem);
  134. public
  135. constructor create;
  136. function AddButton (aname, avalue, acaption : string) : TFormButtonItem;
  137. function AddButton (aname, acaption : string) : TFormButtonItem;
  138. function AddButton (acaption : string) : TFormButtonItem;
  139. property Items [index : integer] : TFormButtonItem read GetItem write SetItem;
  140. end;
  141. TCellType = (ctEmpty, ctInput, ctLabel, ctProducer, ctSpanned);
  142. { TTableCell }
  143. TTableCell = class (TCollectionItem)
  144. private
  145. FAlignHor: THTMLalign;
  146. FAlignVer: THTMLvalign;
  147. FCaption: string;
  148. FCellType: TCellType;
  149. FChecked: boolean;
  150. FColSpan: integer;
  151. FEndRow: boolean;
  152. FFormField: TFormFieldItem;
  153. FIncludeBreak: boolean;
  154. FInputType: TFormInputType;
  155. FIsLabel: boolean;
  156. FLink: string;
  157. FMaxLength: integer;
  158. FName: string;
  159. FProducer: THTMLContentProducer;
  160. FRowSpan: integer;
  161. FSize: integer;
  162. FSpanned: boolean;
  163. FValue: string;
  164. public
  165. function WriteContent (aWriter : THTMLWriter) : THTMLCustomElement;
  166. function WriteHeader (aWriter : THTMLWriter) : THTMLCustomElement;
  167. property FormField : TFormFieldItem read FFormField write FFormField;
  168. // field definition that origintated this cell
  169. property IsLabel : boolean read FIsLabel write FIsLabel;
  170. // Label or Value ?
  171. property Caption : string read FCaption write FCaption;
  172. // label to place with the edit/value if not separateLabel
  173. property IncludeBreak : boolean read FIncludeBreak write FIncludeBreak;
  174. // place <br> between label and edit/value if label is included in cell
  175. property CellType : TCellType read FCellType write FCellType;
  176. { Cell properties: }
  177. property ColSpan : integer read FColSpan write FColSpan;
  178. property RowSpan : integer read FRowSpan write FRowSpan;
  179. property AlignVertical : THTMLvalign read FAlignVer write FAlignVer default vaEmpty;
  180. property AlignHorizontal : THTMLalign read FAlignHor write FAlignHor default alEmpty;
  181. property Value : string read FValue write FValue;
  182. // Contains the text for labels, or the value for input, or unused for producer and empty
  183. { properties to correctly generate the rows and the table ends }
  184. property EndOfRow : boolean read FEndRow write FEndRow;
  185. property SpannedOut : boolean read FSpanned write FSpanned;
  186. { only for input: }
  187. property Name : string read FName write FName;
  188. // name of the control
  189. property InputType : TFormInputType read FInputType write FInputType;
  190. // type of the input element
  191. property Size : integer read FSize write FSize;
  192. // size of text input element
  193. property MaxLength : integer read FMaxLength write FMaxLength;
  194. // MaxLength of text input element
  195. property Checked : boolean read FChecked write FChecked;
  196. // checked or not for radio,checkbox
  197. { only for labels: }
  198. property Link : string read FLink write FLink;
  199. // link to place around the text
  200. { only for producers: }
  201. property Producer : THTMLContentProducer read FProducer write FProducer;
  202. // producer to include
  203. end;
  204. { TTableDef }
  205. TTableDef = class (TCollection)
  206. private
  207. fCols, fRows : integer;
  208. function GetCell(x, y : integer): TTableCell;
  209. function GetItem(index: integer): TTableCell;
  210. public
  211. Constructor Create (acols, arows : integer);
  212. function CopyTablePosition (position : TTablePosition) : TTableCell;
  213. property Cells [x,y : integer] : TTableCell read GetCell; default;
  214. property items [index:integer] : TTableCell read GetItem;
  215. end;
  216. TButtonVerPosition = (bvpTop, bvpBottom);
  217. TButtonVerPositionSet = set of TButtonVerPosition;
  218. TButtonHorPosition = (bhpLeft, bhpCenter, bhpJustify, bhpRight);
  219. TFormMethod = (fmGet, fmPost);
  220. { THTMLDatasetFormProducer }
  221. THTMLDatasetFormProducer = class (THTMLContentProducer)
  222. private
  223. FOnInitializeProducer : TProducerEvent;
  224. FOnFieldChecked : TFieldCheckEvent;
  225. FAfterTBodyCreate,
  226. FAfterTableCreate : THTMLElementEvent;
  227. FAfterButtonCreate: TButtonEvent;
  228. FAfterCellCreate: TFieldCellEvent;
  229. Fbuttonrow: TFormButtonCollection;
  230. FButtonsHor: TButtonHorPosition;
  231. FButtonsVer: TButtonVerPositionSet;
  232. FControls: TFormFieldCollection;
  233. FDatasource: TDatasource;
  234. FFormAction: string;
  235. FFormMethod: TFormMethod;
  236. FIncludeHeader: boolean;
  237. FSeparateLabel: boolean;
  238. FTableCols: integer;
  239. FTableRows: integer;
  240. FTableDef : TTableDef;
  241. FPage: integer;
  242. FRecordsPerPage: integer;
  243. procedure SetIncludeHeader(const AValue: boolean);
  244. procedure SetSeparateLabel(const AValue: boolean);
  245. procedure WriteButtons (aWriter : THTMLWriter);
  246. procedure WriteTableDef (aWriter : THTMLWriter);
  247. procedure WriteHeaderTableDef (aWriter : THTMLWriter);
  248. procedure CorrectCellSpans;
  249. procedure SearchControlFields;
  250. protected
  251. function WriteContent (aWriter : THTMLWriter) : THTMLCustomElement; override;
  252. procedure FillTableDef (IsHeader:boolean); virtual;
  253. procedure ControlToTableDef (aControldef : TFormFieldItem; IsHeader:boolean); virtual; abstract;
  254. function StartForm (aWriter : THTMLWriter) : THTMLCustomElement; virtual;
  255. procedure EndForm (aWriter : THTMLWriter); virtual;
  256. property TableDef : TTableDef read FTableDef;
  257. function SingleRecord : boolean; dynamic;
  258. // generate form for 1 record or for the selected pages
  259. property RecordsPerPage : integer read FRecordsPerPage write FRecordsPerPage default 20;
  260. // number of records to show
  261. property Page : integer read FPage write FPage default -1;
  262. // page to show. -1 shows all records. zero based
  263. property IncludeHeader : boolean read FIncludeHeader write SetIncludeHeader;
  264. // create a header cell for each control
  265. public
  266. constructor create (aOwner : TComponent); override;
  267. destructor destroy; override;
  268. published
  269. property FormAction : string read FFormAction write FFormAction;
  270. // action of the form (link), if not given; don't use a form element
  271. property FormMethod : TFormMethod read FFormMethod write FFormMethod;
  272. // method of the form, Get or Post
  273. Property DataSource : TDataSource read FDataSource write FDataSource;
  274. // the data to use
  275. property Controls : TFormFieldCollection read FControls;
  276. // configuration of the fields and how to generate the html
  277. property SeparateLabel : boolean read FSeparateLabel write SetSeparateLabel;
  278. // place label and value/edit in same table cell
  279. property buttonrow : TFormButtonCollection read Fbuttonrow;
  280. // buttons to place in the form
  281. property TableCols : integer read FTableCols write FTableCols default 2;
  282. // number columns in the grid for 1 record
  283. property TableRows : integer read FTableRows write FTableRows;
  284. // number of rows in the grid for 1 record
  285. property ButtonsHorizontal : TButtonHorPosition read FButtonsHor write FButtonsHor default bhpleft;
  286. // where to place the buttons horizontally
  287. property ButtonsVertical : TButtonVerPositionSet read FButtonsVer write FButtonsVer default [bvpTop,bvpBottom];
  288. // where to place the buttons vertically
  289. property OnInitializeProducer : TProducerEvent read FOnInitializeProducer write FOnInitializeProducer;
  290. // Called before the producer creates it's HTML code
  291. property AfterCellCreate : TFieldCellEvent read FAfterCellCreate write FAfterCellCreate;
  292. // Called after each creation of a cell in the table makeup in the form
  293. property AfterButtonCreate : TButtonEvent read FAfterButtonCreate write FAfterButtonCreate;
  294. // Called after each creation of a button
  295. property AfterTableCreate : THTMLElementEvent read FAfterTableCreate write FAfterTableCreate;
  296. // Called after the creation of the table
  297. property AfterTBodyCreate : THTMLElementEvent read FAfterTBodyCreate write FAfterTBodyCreate;
  298. // Called after finishing the tbody of each record
  299. property OnFieldChecked : TFieldCheckEvent read FOnFieldChecked write FOnFieldChecked;
  300. // return if the field is true or false if the false string differs from '0','false','-'
  301. end;
  302. { THTMLDatasetFormEditProducer }
  303. THTMLDatasetFormEditProducer = class (THTMLDatasetFormProducer)
  304. procedure ControlToTableDef (aControldef : TFormFieldItem; IsHeader:boolean); override;
  305. end;
  306. { THTMLDatasetFormShowProducer }
  307. THTMLDatasetFormShowProducer = class (THTMLDatasetFormProducer)
  308. protected
  309. procedure ControlToTableDef (aControldef : TFormFieldItem; IsHeader:boolean); override;
  310. end;
  311. { THTMLDatasetFormGridProducer }
  312. THTMLDatasetFormGridProducer = class (THTMLDatasetFormProducer)
  313. protected
  314. procedure ControlToTableDef (aControldef : TFormFieldItem; IsHeader:boolean); override;
  315. function SingleRecord : boolean; override;
  316. public
  317. constructor Create (aOwner : TComponent); override;
  318. published
  319. property RecordsPerPage;
  320. property Page;
  321. property IncludeHeader;
  322. end;
  323. implementation
  324. { TTableDef }
  325. function TTableDef.GetItem(index: integer): TTableCell;
  326. begin
  327. result := TTableCell (inherited items[index]);
  328. end;
  329. function TTableDef.GetCell(x, y : integer): TTableCell;
  330. var r : integer;
  331. begin
  332. r := x + (y * fcols);
  333. result := getItem (r);
  334. end;
  335. constructor TTableDef.Create(acols, arows: integer);
  336. var r, t : integer;
  337. begin
  338. inherited create (TTableCell);
  339. fRows := aRows;
  340. fCols := aCols;
  341. for r := 1 to aRows do
  342. begin
  343. for t := 1 to aCols-1 do
  344. Add;
  345. TTableCell(Add).EndOfRow := True;
  346. end;
  347. end;
  348. function TTableDef.CopyTablePosition(position: TTablePosition): TTableCell;
  349. begin
  350. result := Cells[position.left,position.top];
  351. with result do
  352. begin
  353. AlignHorizontal := position.AlignHorizontal;
  354. AlignVertical := position.FAlignVer;
  355. ColSpan := position.ColSpan;
  356. RowSpan := position.RowSpan;
  357. end;
  358. end;
  359. { TTablePosition }
  360. procedure TTablePosition.AssignTo(Dest: TPersistent);
  361. begin
  362. inherited AssignTo(Dest);
  363. if dest is TTablePosition then
  364. with TTablePosition(Dest) do
  365. begin
  366. FTop := self.FTop;
  367. FLeft := self.FLeft;
  368. FColSpan := self.FColSpan;
  369. FRowSpan := self.FRowSpan;
  370. FAlignVer := self.FAlignVer;
  371. FalignHor := self.FAlignHor;
  372. end;
  373. end;
  374. constructor TTablePosition.create;
  375. begin
  376. inherited create;
  377. FColSpan := 1;
  378. FRowSpan := 1;
  379. FAlignVer := vaEmpty;
  380. FAlignHor := alEmpty;
  381. end;
  382. { TFormFieldItem }
  383. procedure TFormFieldItem.SetLabelPos(const AValue: TTablePosition);
  384. begin
  385. FLabelPos.assign(AValue);
  386. end;
  387. procedure TFormFieldItem.SetValuePos(const AValue: TTablePosition);
  388. begin
  389. FValuePos.assign(AValue);
  390. end;
  391. procedure TFormFieldItem.AssignTo(Dest: TPersistent);
  392. begin
  393. inherited AssignTo(Dest);
  394. if dest is TFormFieldItem then
  395. with TFormFIeldItem(Dest) do
  396. begin
  397. FAction := self.FAction;
  398. FFieldName := self.FFieldName;
  399. FInputType := self.FInputType;
  400. FLabelCaption := self.FLabelCaption;
  401. FLabelPos.assign (self.FLabelPos);
  402. FProducer := self.FProducer;
  403. FValuePos.assign(self.FValuePos);
  404. end;
  405. end;
  406. constructor TFormFieldItem.Create(ACollection: TCollection);
  407. begin
  408. inherited Create(ACollection);
  409. FLabelPos := TTablePosition.Create;
  410. FValuePos := TTablePosition.Create;
  411. end;
  412. destructor TFormFieldItem.Destroy;
  413. begin
  414. FLabelPos.Free;
  415. FValuePos.Free;
  416. inherited Destroy;
  417. end;
  418. { TFormFieldCollection }
  419. function TFormFieldCollection.GetItem(index : integer): TFormFieldItem;
  420. begin
  421. result := TFormFieldItem(inherited items[index]);
  422. end;
  423. procedure TFormFieldCollection.SetItem(index : integer;
  424. const AValue: TFormFieldItem);
  425. begin
  426. inherited items[index] := AValue;
  427. end;
  428. constructor TFormFieldCollection.create;
  429. begin
  430. inherited create (TFormFieldItem);
  431. end;
  432. function TFormFieldCollection.AddField(afieldname, acaption: string): TFormFieldItem;
  433. begin
  434. result := TFormFieldItem (Add);
  435. result.fieldname := afieldname;
  436. result.labelcaption := acaption;
  437. end;
  438. { TFormButtonItem }
  439. procedure TFormButtonItem.AssignTo(Dest: TPersistent);
  440. begin
  441. inherited AssignTo(Dest);
  442. if dest is TFormButtonItem then
  443. with TFormButtonItem(Dest) do
  444. begin
  445. FButtonType := self.FButtonType;
  446. FCaption := self.FCaption;
  447. FImage := self.FImage;
  448. FImagePlace := self.FImagePlace;
  449. FName := self.FName;
  450. FValue := self.FValue;
  451. end;
  452. end;
  453. constructor TFormButtonItem.create(ACollection: TCollection);
  454. begin
  455. inherited create(ACollection);
  456. ButtonType := fbtPushButton;
  457. end;
  458. { TFormButtonCollection }
  459. function TFormButtonCollection.GetItem(index: integer): TFormButtonItem;
  460. begin
  461. result := TFormButtonItem(inherited items[index]);
  462. end;
  463. procedure TFormButtonCollection.SetItem(index: integer;
  464. const AValue: TFormButtonItem);
  465. begin
  466. inherited items[index] := AValue;
  467. end;
  468. constructor TFormButtonCollection.create;
  469. begin
  470. inherited create (TFormButtonItem);
  471. end;
  472. function TFormButtonCollection.AddButton(aname, avalue, acaption: string): TFormButtonItem;
  473. begin
  474. result := TFormButtonItem(Add);
  475. with result do
  476. begin
  477. name := aname;
  478. value := avalue;
  479. caption := acaption;
  480. end;
  481. end;
  482. function TFormButtonCollection.AddButton(aname, acaption: string): TFormButtonItem;
  483. begin
  484. result := AddButton (aName, aCaption, acaption);
  485. end;
  486. function TFormButtonCollection.AddButton(acaption: string): TFormButtonItem;
  487. begin
  488. result := AddButton (acaption, acaption, acaption);
  489. end;
  490. { THTMLDatasetFormProducer }
  491. procedure THTMLDatasetFormProducer.WriteButtons(aWriter: THTMLWriter);
  492. procedure WriteButton (aButton : TFormButtonItem);
  493. const ButtonTypes : array[TFormButtontype] of THTMLbuttontype = (btsubmit,btreset,btbutton);
  494. var b : THTML_Button;
  495. begin
  496. with aWriter do
  497. begin
  498. b := Startbutton;
  499. with b do
  500. begin
  501. Name := aButton.name;
  502. Value := aButton.value;
  503. TheType := ButtonTypes[aButton.ButtonType];
  504. if aButton.Image = '' then
  505. Text (aButton.Caption)
  506. else
  507. begin
  508. if aButton.ImagePlace in [ipAfter, ipUnder] then
  509. begin
  510. Text (aButton.Caption);
  511. if aButton.ImagePlace = ipUnder then
  512. linebreak;
  513. end;
  514. with image do
  515. begin
  516. src := aButton.image;
  517. if aButton.ImagePlace = ipOnly then
  518. alt := aButton.Caption;
  519. end;
  520. if aButton.ImagePlace in [ipBefore, ipAbove] then
  521. begin
  522. if aButton.ImagePlace = ipAbove then
  523. linebreak;
  524. Text (aButton.Caption);
  525. end;
  526. end;
  527. if assigned (FAfterButtonCreate) then
  528. FAfterButtonCreate (self, aButton, b);
  529. Endbutton;
  530. end;
  531. end;
  532. end;
  533. const ButHorAlign : array[TButtonHorPosition] of THTMLalign = (alleft,alcenter,aljustify,alright);
  534. var r : integer;
  535. begin
  536. with aWriter do
  537. begin
  538. StartTableRow;
  539. with StartTableCell do
  540. begin
  541. ColSpan := inttostr(FTableCols);
  542. align := ButHorAlign[ButtonsHorizontal];
  543. end;
  544. for r := 0 to buttonrow.count-1 do
  545. WriteButton (buttonrow.Items[r]);
  546. EndTableCell;
  547. EndTableRow;
  548. end;
  549. end;
  550. procedure THTMLDatasetFormProducer.SetSeparateLabel(const AValue: boolean);
  551. begin
  552. if AValue <> FSeparateLabel then
  553. begin
  554. FSeparateLabel := AValue;
  555. if AValue then
  556. FIncludeHeader := false;
  557. end;
  558. end;
  559. procedure THTMLDatasetFormProducer.SetIncludeHeader(const AValue: boolean);
  560. begin
  561. if FIncludeHeader <> AValue then
  562. begin
  563. FIncludeHeader := AValue;
  564. if AValue then
  565. SeparateLabel := false;
  566. end;
  567. end;
  568. procedure THTMLDatasetFormProducer.WriteTableDef(aWriter: THTMLWriter);
  569. var r : integer;
  570. c : THTMLCustomelement;
  571. begin
  572. c := aWriter.Starttablebody;
  573. if assigned (FAfterTBodyCreate) then
  574. FAfterTBodyCreate (self, c);
  575. aWriter.StartTableRow;
  576. with tabledef do
  577. begin
  578. for r := 0 to count-2 do
  579. with TTableCell (Items[r]) do
  580. begin
  581. if CellType <> ctSpanned then
  582. begin
  583. if (CellType = ctProducer) and assigned (FOnInitializeProducer) then
  584. FOnInitializeProducer (self, FFormField, Producer);
  585. c := WriteContent(aWriter);
  586. if assigned (FAfterCellCreate) then
  587. FAfterCellCreate(self, Items[r].FormField, IsLabel, c);
  588. end;
  589. if EndOfRow then
  590. begin
  591. aWriter.EndTableRow;
  592. aWriter.StartTableRow;
  593. end;
  594. end;
  595. TTableCell(Items[Count-1]).WriteContent(aWriter);
  596. end;
  597. aWriter.EndTableRow;
  598. aWriter.Endtablebody;
  599. end;
  600. procedure THTMLDatasetFormProducer.WriteHeaderTableDef(aWriter: THTMLWriter);
  601. var r : integer;
  602. c : THTMLCustomelement;
  603. begin
  604. aWriter.Starttablehead;
  605. aWriter.StartTableRow;
  606. with tabledef do
  607. begin
  608. for r := 0 to count-2 do
  609. with TTableCell (Items[r]) do
  610. begin
  611. c := WriteHeader(aWriter);
  612. if assigned (FAfterCellCreate) then
  613. FAfterCellCreate(self, Items[r].FormField, true, c);
  614. if EndOfRow then
  615. begin
  616. aWriter.EndTableRow;
  617. aWriter.StartTableRow;
  618. end;
  619. end;
  620. TTableCell(Items[Count-1]).WriteContent(aWriter);
  621. end;
  622. aWriter.EndTableRow;
  623. aWriter.Endtablehead;
  624. end;
  625. procedure THTMLDatasetFormProducer.CorrectCellSpans;
  626. var r, s, t : integer;
  627. c : TTableCell;
  628. ReachedEnd : boolean;
  629. begin
  630. for r := 0 to TableDef.count-1 do
  631. with TableDef.items[r] do
  632. if CellType <> ctSpanned then
  633. begin
  634. // CollSpan marking other cells as spanned
  635. s := 1;
  636. c := TableDef.Items[r];
  637. while (s < ColSpan) and not c.EndOfRow do
  638. begin
  639. c := TableDef.Items[r+s];
  640. c.celltype := ctSpanned;
  641. inc (s);
  642. end;
  643. // the same for rowsapn
  644. s := 1;
  645. t := r + (s*tablecols);
  646. while (s < rowspan) and (t < TableDef.count) do
  647. begin
  648. TableDef.items[t].CellType := ctSpanned;
  649. inc (s);
  650. inc (t, tablecols);
  651. end;
  652. end;
  653. end;
  654. procedure THTMLDatasetFormProducer.SearchControlFields;
  655. var r : integer;
  656. begin
  657. for r := 0 to FControls.count-1 do
  658. with FControls.items[r] do
  659. FField := datasource.dataset.FindField(FFieldname);
  660. end;
  661. function THTMLDatasetFormProducer.StartForm(aWriter: THTMLWriter) : THTMLCustomElement;
  662. const MethodAttribute : array[TFormMethod] of string = ('GET','POST');
  663. var t : THTMLCustomElement;
  664. begin
  665. if FormAction <> '' then
  666. begin
  667. result := aWriter.Startform;
  668. with THTML_Form(result) do
  669. begin
  670. method := MethodAttribute[self.FormMethod];
  671. action := FormAction;
  672. end;
  673. t := aWriter.Starttable;
  674. end
  675. else
  676. begin
  677. t := aWriter.Starttable;
  678. result := t;
  679. end;
  680. if assigned (FAfterTableCreate) then
  681. FAfterTableCreate (self, t);
  682. end;
  683. procedure THTMLDatasetFormProducer.EndForm(aWriter: THTMLWriter);
  684. begin
  685. with aWriter do
  686. begin
  687. EndTable;
  688. if FormAction <> '' then
  689. Endform;
  690. end;
  691. end;
  692. function THTMLDatasetFormProducer.WriteContent(aWriter: THTMLWriter): THTMLCustomElement;
  693. var r : integer;
  694. begin
  695. if assigned (datasource) and assigned(datasource.dataset) then
  696. begin
  697. Ftabledef := TTableDef.Create (TableCols, TableRows);
  698. try
  699. SearchControlFields;
  700. result := StartForm (aWriter);
  701. if bvpTop in ButtonsVertical then
  702. WriteButtons (aWriter);
  703. if SingleRecord then
  704. begin
  705. FillTableDef (false);
  706. CorrectCellSpans;
  707. WriteTableDef (aWriter);
  708. end
  709. else
  710. with datasource.dataset do
  711. begin
  712. if FIncludeHeader then
  713. begin
  714. FillTableDef (true);
  715. CorrectCellSpans;
  716. WriteHeaderTableDef (aWriter);
  717. end;
  718. if Page < 0 then
  719. first
  720. else
  721. RecNo := ((Page-1) * RecordsPerPage) + 1; // zero based? yes: + 1 has to be deleted
  722. r := 0;
  723. while not eof and (r < RecordsPerPage) do
  724. begin
  725. FillTableDef (false);
  726. CorrectCellSpans;
  727. WriteTableDef (aWriter);
  728. Next;
  729. inc (r);
  730. end;
  731. end;
  732. if bvpBottom in ButtonsVertical then
  733. WriteButtons (aWriter);
  734. EndForm (aWriter)
  735. finally
  736. tabledef.Free;
  737. end;
  738. end;
  739. end;
  740. procedure THTMLDatasetFormProducer.FillTableDef (IsHeader:boolean);
  741. var r : integer;
  742. begin
  743. for r := 0 to Controls.Count-1 do
  744. ControlToTableDef (Controls.items[r], IsHeader);
  745. end;
  746. function THTMLDatasetFormProducer.SingleRecord: boolean;
  747. begin
  748. result := true;
  749. end;
  750. constructor THTMLDatasetFormProducer.create(aOwner: TComponent);
  751. begin
  752. inherited create(aOwner);
  753. FTableCols := 2;
  754. FButtonsHor := bhpLeft;
  755. FButtonsVer := [bvpTop, bvpBottom];
  756. Fbuttonrow := TFormButtonCollection.create;
  757. FControls := TFormFieldCollection.Create;
  758. end;
  759. destructor THTMLDatasetFormProducer.destroy;
  760. begin
  761. Fbuttonrow.Free;
  762. FControls.Free;
  763. inherited destroy;
  764. end;
  765. { THTMLDatasetFormEditProducer }
  766. procedure THTMLDatasetFormEditProducer.ControlToTableDef (aControldef : TFormFieldItem; IsHeader:boolean);
  767. procedure PlaceFieldValue;
  768. var check : boolean;
  769. begin
  770. with TableDef.CopyTablePosition(aControlDef.ValuePos) do
  771. begin
  772. case aControlDef.inputtype of
  773. fittext,
  774. fitpassword,
  775. fitcheckbox,
  776. fitradio,
  777. fitfile,
  778. fithidden,
  779. fittextarea :
  780. begin
  781. CellType := ctInput;
  782. InputType := aControlDef.InputType;
  783. Name := aControlDef.Field.FieldName;
  784. Size := aControlDef.Field.DisplayWidth;
  785. MaxLength := aControldef.Field.Size;
  786. if aControlDef.inputType in [fitcheckbox,fitradio] then
  787. begin
  788. with aControlDef.Field do
  789. Checked := not isnull and (asstring <> '0') and (asstring <> '-')
  790. and (comparetext(asstring,'false') <> 0);
  791. if assigned (FOnFieldChecked) then
  792. FOnFieldChecked (aControlDef.Field, check);
  793. Checked := check;
  794. end;
  795. end;
  796. fitproducer :
  797. begin
  798. CellType := ctProducer;
  799. Producer := aControlDef.Producer;
  800. end;
  801. fitrecordselection : ;
  802. end;
  803. IsLabel := false;
  804. Value := aControlDef.FField.asstring;
  805. if not FSeparateLabel and not FIncludeHeader then
  806. begin
  807. Caption := aControldef.LabelCaption;
  808. IncludeBreak := aControldef.LabelAbove;
  809. end;
  810. end;
  811. end;
  812. procedure PlaceLabel;
  813. begin
  814. with TableDef.CopyTablePosition(aControlDef.LabelPos) do
  815. begin
  816. CellType := ctLabel;
  817. IsLabel := true;
  818. Value := aControldef.labelcaption;
  819. end;
  820. end;
  821. begin
  822. if assigned (aControlDef.FField) then
  823. PlaceFieldValue;
  824. if FSeparateLabel and (aControlDef.LabelCaption <> '') then
  825. PlaceLabel;
  826. end;
  827. { THTMLDatasetFormShowProducer }
  828. (**** TTableCell *****
  829. property IsLabel : boolean read FIsLabel write FIsLabel;
  830. // Label or Value ?
  831. property CellType : TCellType read FCellType write FCellType;
  832. ctEmpty, ctInput, ctLabel, ctProducer, ctSpanned
  833. { Cell properties: }
  834. property ColSpan : integer read FColSpan write FColSpan;
  835. property RowSpan : integer read FRowSpan write FRowSpan;
  836. property AlignVertical : THTMLvalign read FAlignVer write FAlignVer default vaEmpty;
  837. property AlignHorizontal : THTMLalign read FAlignHor write FAlignHor default alEmpty;
  838. property Value : string read FValue write FValue;
  839. // Contains the text for labels, or the value for input, or unused for producer and empty
  840. { only for input: }
  841. property Name : string read FName write FName;
  842. // name of the control
  843. property InputType : TFormInputType read FInputType write FInputType;
  844. // type of the input element
  845. property Size : integer read FSize write FSize;
  846. // size of text input element
  847. property MaxLength : integer read FMaxLength write FMaxLength;
  848. // MaxLength of text input element
  849. property Checked : boolean read FChecked write FChecked;
  850. // checked or not for radio,checkbox
  851. { only for labels: }
  852. property Link : string read FLink write FLink;
  853. // link to place around the text
  854. { only for producers: }
  855. property Producer : THTMLContentProducer read FProducer write FProducer;
  856. // producer to include
  857. ***** TFormFieldItem *****
  858. property Fieldname : string read FFieldName write FFieldname;
  859. property Field : TField
  860. // the field to show/edit
  861. property LabelCaption : string read FLabelCaption write FLabelCaption;
  862. // the text to show for the control
  863. property InputType : TFormInputType read FInputType write FInputType default fittext;
  864. // the type of form control to use
  865. (fittext,fitpassword,fitcheckbox,fitradio,fitfile,fithidden,fitproducer,fittextarea,fitrecordselection)
  866. property Producer : THTMLContentProducer read FProducer write FProducer;
  867. // the producer to include when generating the value
  868. property Action : string read FAction write FAction;
  869. // when showing the link to include in the value
  870. property LabelPos : TTablePosition read FLabelPos write SetLabelPos;
  871. // place of the label in the table-grid
  872. property ValuePos : TTablePosition read FValuePos write SetValuePos;
  873. // place of the value in the table-grid *)
  874. procedure THTMLDatasetFormShowProducer.ControlToTableDef (aControldef : TFormFieldItem; IsHeader:boolean);
  875. procedure PlaceFieldValue;
  876. begin
  877. with TableDef.CopyTablePosition(aControlDef.ValuePos) do
  878. begin
  879. CellType := ctLabel;
  880. IsLabel := false;
  881. Value := aControlDef.FField.asstring;
  882. if not FSeparateLabel and not FIncludeHeader then
  883. begin
  884. Caption := aControldef.LabelCaption;
  885. IncludeBreak := aControldef.LabelAbove;
  886. end;
  887. end;
  888. end;
  889. procedure PlaceLabel;
  890. begin
  891. with TableDef.CopyTablePosition(aControlDef.LabelPos) do
  892. begin
  893. CellType := ctLabel;
  894. IsLabel := true;
  895. Value := aControldef.labelcaption;
  896. end;
  897. end;
  898. begin
  899. if assigned (aControlDef.FField) then
  900. PlaceFieldValue;
  901. if FSeparateLabel and (aControlDef.LabelCaption <> '') then
  902. PlaceLabel;
  903. end;
  904. { THTMLDatasetFormGridProducer }
  905. procedure THTMLDatasetFormGridProducer.ControlToTableDef (aControldef : TFormFieldItem; IsHeader:boolean);
  906. procedure PlaceFieldValue;
  907. begin
  908. with TableDef.CopyTablePosition(aControlDef.ValuePos) do
  909. begin
  910. CellType := ctLabel;
  911. IsLabel := false;
  912. Value := aControlDef.FField.asstring;
  913. if not FSeparateLabel and not FIncludeHeader then
  914. begin
  915. Caption := aControldef.LabelCaption;
  916. IncludeBreak := aControldef.LabelAbove;
  917. end;
  918. end;
  919. end;
  920. procedure PlaceLabel;
  921. begin
  922. with TableDef.CopyTablePosition(aControlDef.LabelPos) do
  923. begin
  924. CellType := ctLabel;
  925. IsLabel := true;
  926. Value := aControldef.labelcaption;
  927. end;
  928. end;
  929. begin
  930. if assigned (aControlDef.FField) then
  931. PlaceFieldValue;
  932. if FSeparateLabel and (aControlDef.LabelCaption <> '') then
  933. PlaceLabel;
  934. end;
  935. function THTMLDatasetFormGridProducer.SingleRecord: boolean;
  936. begin
  937. Result := false;
  938. end;
  939. constructor THTMLDatasetFormGridProducer.Create(aOwner: TComponent);
  940. begin
  941. inherited create(aOwner);
  942. RecordsPerPage := 20;
  943. Page := -1;
  944. end;
  945. { TTableCell }
  946. function TTableCell.WriteContent(aWriter: THTMLWriter) : THTMLCustomElement;
  947. procedure WriteLabel;
  948. var HasLink : boolean;
  949. begin
  950. HasLink := (Link <> '');
  951. if HasLink then
  952. aWriter.Anchor(Value).href := Link
  953. else
  954. aWriter.Text (Value);
  955. end;
  956. procedure WriteTextArea;
  957. begin
  958. aWriter.textarea(value).name := Name;
  959. end;
  960. procedure WriteInput;
  961. var s, m : string;
  962. begin
  963. if size > 0 then
  964. s := inttostr(size)
  965. else
  966. s := '';
  967. if MaxLength > 0 then
  968. m := inttostr(MaxLength)
  969. else
  970. m := '';
  971. case InputType of
  972. fittext :
  973. with aWriter.FormText (Name, Value) do
  974. begin
  975. Size := s;
  976. MaxLength := m;
  977. end;
  978. fitpassword :
  979. with aWriter.FormPasswd (Name) do
  980. begin
  981. if self.Value <> '' then
  982. Value := self.value;
  983. Size := s;
  984. MaxLength := m;
  985. end;
  986. fitcheckbox, fitrecordselection :
  987. aWriter.FormCheckbox (Name, Value, checked);
  988. fitradio :
  989. aWriter.FormRadio(Name, Value, checked);
  990. fitfile :
  991. aWriter.FormFile(Name, Value);
  992. fithidden :
  993. aWriter.FormHidden (Name, Value);
  994. end;
  995. end;
  996. procedure WriteProducer;
  997. begin
  998. with Producer do
  999. begin
  1000. ParentElement := aWriter.CurrentElement;
  1001. HTMLDocument := aWriter.Document;
  1002. WriteContent (aWriter);
  1003. end;
  1004. end;
  1005. var c : THTML_td;
  1006. begin
  1007. if CellType <> ctSpanned then
  1008. with aWriter do
  1009. begin
  1010. c := Starttablecell;
  1011. with c do
  1012. begin
  1013. if self.ColSpan > 1 then
  1014. colspan := IntToStr(self.Colspan);
  1015. if self.RowSpan > 1 then
  1016. Rowspan := IntToStr(self.Rowspan);
  1017. align := AlignHorizontal;
  1018. valign := AlignVertical;
  1019. end;
  1020. if Self.Caption <> '' then
  1021. begin
  1022. span(self.caption);
  1023. if IncludeBreak then
  1024. linebreak;
  1025. end;
  1026. case CellType of
  1027. ctEmpty : ;
  1028. ctInput :
  1029. if InputType = fittextarea then
  1030. WriteTextArea
  1031. else
  1032. WriteInput;
  1033. ctLabel : WriteLabel;
  1034. ctProducer : WriteProducer;
  1035. end;
  1036. Endtablecell;
  1037. result := c;
  1038. end
  1039. else
  1040. result := nil;
  1041. end;
  1042. function TTableCell.WriteHeader(aWriter: THTMLWriter) : THTMLCustomElement;
  1043. var c : THTML_th;
  1044. s : string;
  1045. begin
  1046. with aWriter do
  1047. begin
  1048. c := Starttableheadcell;
  1049. with c do
  1050. begin
  1051. if self.ColSpan > 1 then
  1052. ColSpan := IntToStr(self.Colspan);
  1053. if self.RowSpan > 1 then
  1054. RowSpan := IntToStr(self.Rowspan);
  1055. align := AlignHorizontal;
  1056. valign := AlignVertical;
  1057. end;
  1058. if CellType <> ctLabel then
  1059. begin
  1060. s := FormField.LabelCaption;
  1061. if self.Link <> '' then
  1062. aWriter.Anchor(s).href := self.Link
  1063. else
  1064. aWriter.Text (s);
  1065. end
  1066. else
  1067. aWriter.Text ('');
  1068. Endtablecell;
  1069. result := c;
  1070. end;
  1071. end;
  1072. end.