dbwhtml.pp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710
  1. {
  2. $Id$
  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. {$mode objfpc}
  12. {$H+}
  13. unit dbwhtml;
  14. Interface
  15. uses sysutils,classes,db,whtml;
  16. Type
  17. THTMLAlign = (haDefault,haLeft,haRight,haCenter); // Compatible with Delphi.
  18. THTMLVAlign = (haVDefault,haTop,haMiddle,haBottom,haBaseLine); // Compatible with Delphi.
  19. TGetCellContentsEvent = Procedure (Sender : TObject; Var CellData : String) of object;
  20. TCellAttributesEvent = Procedure (Sender : TObject;
  21. Var BGColor : String;
  22. Var Align : THTMLAlign;
  23. Var VAlign : THTMLValign;
  24. Var CustomAttr : String) of Object;
  25. TRowAttributesEvent = Procedure (Sender : TObject;
  26. Var BGColor : String;
  27. Var Align : THTMLAlign;
  28. Var VAlign : THTMLValign;
  29. Var CustomAttr : String) of Object;
  30. TRowAttributes = Class(TPersistent)
  31. Private
  32. FAlign : THTMLAlign;
  33. FVAlign : THTMLVAlign;
  34. FBGColor : String;
  35. FCustom : String;
  36. Public
  37. Procedure Assign(Source : TPersistent); Override;
  38. Property Align : THTMLAlign Read FAlign Write FAlign;
  39. Property BGColor : String Read FBGColor Write FBGColor;
  40. Property Custom : String Read FCustom Write FCustom;
  41. Property VAlign : THTMLVAlign Read FVAlign Write FVAlign;
  42. end;
  43. TTableColumn = Class(TCollectionItem)
  44. private
  45. FActionUrl: String;
  46. FAlign: THTMLAlign;
  47. FVAlign : THTMLVAlign;
  48. FBGColor: String;
  49. FCaptionURL: String;
  50. FFieldName : String;
  51. FCaption : String;
  52. FGetColumn: String;
  53. FGetCellContent : TGetCellContentsEvent;
  54. FImgUrl: String;
  55. Protected
  56. FField : TField; // Filled.
  57. Published
  58. Property FieldName : String Read FFieldName Write FFieldName;
  59. Property Caption : String Read FCaption Write FCaption;
  60. Property ImgUrl : String Read FImgUrl Write FImgUrl;
  61. Property ActionUrl : String Read FActionUrl Write FActionUrl;
  62. Property CaptionURL : String Read FCaptionURL Write FCaptionURL;
  63. Property BGColor : String Read FBGColor Write FBGColor;
  64. Property Align : THTMLAlign read FAlign Write Falign;
  65. Property VAlign : THTMLVAlign Read FValign Write FVAlign;
  66. Property OnGetCellContents : TGetCellContentsEvent Read FGetCellContent Write FGetCellContent;
  67. end;
  68. TTableColumns = Class(TCollection)
  69. Constructor Create;
  70. private
  71. function GetColumn(Index : Integer): TTableColumn;
  72. procedure SetColumn(Index : Integer; const AValue: TTableColumn);
  73. Public
  74. Function FindColumn(ColumnName : String) : TTableColumn;
  75. Function ColumnByName(ColumnName : String) : TTableColumn;
  76. Property Items[Index : Integer] : TTableColumn Read GetColumn Write SetColumn;
  77. end;
  78. THTMLProducer = Class(TComponent)
  79. Private
  80. FDataset : TDataset;
  81. FContents: TMemorySTream;
  82. Function GetContent : String;
  83. Protected
  84. Procedure CheckContents;
  85. Procedure WriteString(S : TStream; Const Value : String);
  86. Procedure WriteString(S : TStream; Const Fmt : String; Args : Array Of Const);
  87. Public
  88. Destructor Destroy; override;
  89. Procedure ClearContent;
  90. Procedure CreateContent; virtual; Abstract;
  91. Property Content : String Read GetContent;
  92. Published
  93. Property Dataset : TDataset Read FDataset Write FDataset;
  94. end;
  95. TTableProducer = Class(THTMLProducer)
  96. Private
  97. FGetRowAttrs: TRowAttributesEvent;
  98. FRowAttributes: TRowAttributes;
  99. FTableColumns : TTableColumns;
  100. FBorder : Boolean;
  101. FBGColor : String;
  102. FCurrentRow : Integer;
  103. FCurrentCol : Integer;
  104. FGetCellAttrs : TCellAttributesEvent;
  105. procedure SetRowAttributes(const AValue: TRowAttributes);
  106. Procedure SetTableColumns(Value : TTableColumns);
  107. Protected
  108. Procedure BindColumns;
  109. Procedure CreateTableColumns; Virtual;
  110. Procedure CreateTableHeader(Stream : TStream);
  111. Procedure CreateHeaderCell(C : TTableColumn; Stream : TStream); virtual;
  112. Procedure CreateTableRow(Stream : TStream);virtual;
  113. Procedure StartTable(Stream : TStream); virtual;
  114. Procedure EndTable(Stream : TStream); virtual;
  115. Procedure EmitFieldCell(C : TTableColumn; Stream : TStream); virtual;
  116. Public
  117. Constructor Create(AOwner : TComponent); override;
  118. Destructor Destroy; virtual;
  119. Function CreateAttr(Const ABGColor : String; A : THTMLAlign; VA : THTMLVAlign; CustomAttr : String) : String;
  120. Procedure Clear;
  121. Procedure CreateColumns(FieldList : TStrings);
  122. Procedure CreateColumns(FieldList : String);
  123. Procedure CreateTable(Stream : TStream);
  124. Procedure CreateTable;
  125. Procedure CreateContent; override;
  126. Property CurrentRow : Integer Read FCurrentRow;
  127. Property CurrentCol : Integer Read FCurrentCol;
  128. Published
  129. Property BGColor : String Read FBGColor Write FBGColor;
  130. Property Border : Boolean Read FBorder Write FBorder;
  131. Property RowAttributes : TRowAttributes Read FRowAttributes Write SetRowAttributes;
  132. Property TableColumns : TTableColumns Read FTableColumns Write SetTableColumns;
  133. Property OnGetCellAttributes : TCellAttributesEvent Read FGetCellAttrs write FGetCellAttrs;
  134. Property OnGetRowAttributes : TRowAttributesEvent Read FGetRowAttrs write FGetRowAttrs;
  135. end;
  136. TComboBoxProducer = Class(THTMLProducer)
  137. private
  138. FDatafield: String;
  139. FInputName: String;
  140. FValue: String;
  141. FValueField: String;
  142. function GetInputName: String;
  143. protected
  144. procedure CreateItem(Stream : TStream; VF,DF : TField; Selected : Boolean); virtual;
  145. Public
  146. Constructor Create(AOwner : TComponent); override;
  147. Destructor Destroy; virtual;
  148. Procedure CreateComboBox(Stream : TStream);
  149. Procedure CreateComboBox;
  150. Procedure CreateContent; override;
  151. Published
  152. Property ValueField : String Read FValueField Write FValueField;
  153. Property DataField : String Read FDatafield Write FDataField;
  154. Property Value : String Read FValue Write FValue;
  155. Property InputName : String Read GetInputName Write FInputName;
  156. end;
  157. TDBHtmlWriter = Class(THTMLWriter)
  158. Protected
  159. Function CreateTableProducer: TTableProducer; virtual;
  160. Public
  161. Procedure CreateTable(Dataset : TDataset);
  162. Procedure CreateTable(Dataset : TDataset; Producer : TTableProducer);
  163. end;
  164. EDBWriter = Class(Exception);
  165. Implementation
  166. Resourcestring
  167. SErrColumnNotFound = 'Column "%s" not found.';
  168. { TTableColumns }
  169. constructor TTableColumns.Create;
  170. begin
  171. inherited Create(TTableColumn);
  172. end;
  173. function TTableColumns.GetColumn(Index : Integer): TTableColumn;
  174. begin
  175. Result:=TTableColumn(Inherited Items[Index]);
  176. end;
  177. procedure TTableColumns.SetColumn(Index : Integer; const AValue: TTableColumn);
  178. begin
  179. Inherited Items[Index]:=AValue;
  180. end;
  181. function TTableColumns.FindColumn(ColumnName: String): TTableColumn;
  182. Var
  183. I : Integer;
  184. begin
  185. Result:=Nil;
  186. I:=Count-1;
  187. While (I>=0) and (CompareText(Items[i].FieldName,ColumnName)<>0) do
  188. Dec(I);
  189. If (I>=0) then
  190. Result:=Items[I];
  191. end;
  192. function TTableColumns.ColumnByName(ColumnName: String): TTableColumn;
  193. begin
  194. Result:=FindColumn(ColumnName);
  195. If (Result=Nil) then
  196. Raise EDBWriter.CreateFmt(SErrColumnNotFound,[ColumnName]);
  197. end;
  198. { TTableProducer }
  199. procedure TTableProducer.BindColumns;
  200. Var
  201. I : Integer;
  202. begin
  203. With FTableColumns do
  204. For I:=0 to Count-1 do
  205. With TTableColumn(Items[I]) do
  206. If (FieldName<>'') then
  207. FField:=FDataset.FieldByName(FieldName)
  208. else
  209. FField:=Nil;
  210. end;
  211. procedure TTableProducer.CreateTableColumns;
  212. begin
  213. FTableColumns:=TTableColumns.Create;
  214. end;
  215. procedure TTableProducer.CreateTableHeader(Stream : TStream);
  216. Var
  217. I : Integer;
  218. begin
  219. WriteString(Stream,'<TR>');
  220. With FTableColumns do
  221. For I:=0 to Count-1 do
  222. begin
  223. FCurrentCol:=I;
  224. CreateHeaderCell(TTableColumn(Items[I]),Stream);
  225. end;
  226. WriteString(Stream,'</TR>'#10);
  227. end;
  228. procedure TTableProducer.CreateHeaderCell(C: TTableColumn; Stream: TStream);
  229. Var
  230. URL : String;
  231. begin
  232. WriteString(Stream,'<TH>');
  233. With C do
  234. begin
  235. If (FCaptionURL<>'') then
  236. begin
  237. URL:=Format(FCaptionURL,[FieldName]);
  238. URL:=Format('<A HREF="%s">',[URL]);
  239. WriteString(Stream,URL);
  240. end;
  241. WriteString(Stream,Caption);
  242. If (FCaptionURL<>'') then
  243. WriteString(Stream,'</A>');
  244. If (FImgURL<>'') then
  245. begin
  246. if (FCaptionURL<>'') then
  247. WriteString(Stream,URL);
  248. WriteString(Stream,'<IMG SRC="%s">',[FImgURL]);
  249. If (FCaptionURL<>'') then
  250. WriteString(Stream,'</A>');
  251. end;
  252. end;
  253. WriteString(Stream,'</TH>');
  254. end;
  255. procedure TTableProducer.CreateTableRow(Stream : TStream);
  256. Var
  257. I : Integer;
  258. BG : String;
  259. A : THTMLAlign;
  260. VA : THTMLVAlign;
  261. RTAG,CustA : String;
  262. begin
  263. With FRowAttributes do
  264. begin
  265. BG:=FBGColor;
  266. A:=FAlign;
  267. VA:=VAlign;
  268. CustA:=FCustom;
  269. end;
  270. If Assigned(FGetRowAttrs) then
  271. FGetRowAttrs(Self,BG,A,VA,CustA);
  272. RTAG:=CreateAttr(BG,A,VA,CustA);
  273. If (RTAG='') then
  274. RTag:='<TR>'
  275. else
  276. RTag:='<TR '+RTag+'>';
  277. WriteString(Stream,RTag);
  278. With FTableColumns do
  279. For I:=0 to Count-1 do
  280. EmitFieldCell(TTableColumn(Items[I]),Stream);
  281. WriteString(Stream,'</TR>'#10);
  282. end;
  283. procedure TTableProducer.StartTable(Stream: TStream);
  284. Var
  285. S : String;
  286. begin
  287. S:='<TABLE';
  288. If Border then
  289. S:=S+' BORDER=1';
  290. If (BGColor<>'') then
  291. S:=S+'BGCOlor="'+BGColor+'"';
  292. S:=S+'>';
  293. WriteString(Stream,S);
  294. end;
  295. procedure TTableProducer.EndTable(Stream: TStream);
  296. begin
  297. WriteString(Stream,'</TABLE>'#10);
  298. end;
  299. Function TTableProducer.CreateAttr(Const ABGColor : String; A : THTMLAlign; VA : THTMLVAlign; CustomAttr : String) : String;
  300. Const
  301. HAligns : Array[THTMLAlign] of string = ('','"left"','"right"','"center"');
  302. VAligns : Array[THTMLVAlign] of string = ('','"top"','"middle"','"bottom"','"baseLine"');
  303. begin
  304. Result:='';
  305. If (ABGColor<>'') then
  306. Result:='BGColor="'+ABGColor+'"';
  307. If (A<>haDefault) then
  308. Result:=Result+' Align='+HAligns[A];
  309. if (VA<>haVDefault) then
  310. Result:=Result+' Align='+VAligns[VA];
  311. If (CustomAttr<>'') then
  312. Result:=Result+' '+CustomAttr;
  313. end;
  314. procedure TTableProducer.EmitFieldCell(C: TTableColumn; Stream: TStream);
  315. Var
  316. URL : String;
  317. BG : String;
  318. A : THTMLAlign;
  319. VA : THTMLVAlign;
  320. CellA,CustA : String;
  321. begin
  322. BG:=C.BGColor;
  323. A:=C.Align;
  324. VA:=C.Valign;
  325. CustA:='';
  326. If Assigned(FGetCellAttrs) then
  327. FGetCellAttrs(Self,BG,A,VA,CustA);
  328. CellA:=CreateAttr(BGColor,A,VA,CustA);
  329. If (CellA='') then
  330. CellA:='<TD>'
  331. else
  332. CellA:='<TD '+CellA+'>';
  333. WriteString(Stream,CellA);
  334. // Reuse for contents.
  335. CellA:='';
  336. If (C.FField<>Nil) then
  337. CellA:=C.FField.AsString;
  338. If Assigned(C.FGetCellContent) then
  339. C.FGetCellContent(Self,CellA);
  340. With C.FField Do
  341. begin
  342. URL:=C.ActionURL;
  343. If (URL<>'') then
  344. begin
  345. URL:=Format(C.ActionURL,[AsString]);
  346. WriteString(Stream,'<A HREF="%s">',[URL]);
  347. end;
  348. WriteString(Stream,CellA);
  349. If (URL<>'') then
  350. WriteString(Stream,'</A>');
  351. end;
  352. WriteString(Stream,'</TD>');
  353. end;
  354. constructor TTableProducer.Create(AOwner : TComponent);
  355. begin
  356. Inherited Create(AOwner);
  357. FRowAttributes:=TRowAttributes.Create;
  358. CreateTableColumns;
  359. FCurrentRow:=-1;
  360. FCurrentCol:=-1;
  361. end;
  362. destructor TTableProducer.Destroy;
  363. begin
  364. FTableColumns.Free;
  365. Inherited;
  366. end;
  367. procedure TTableProducer.Clear;
  368. begin
  369. FTableColumns.Clear;
  370. If Assigned(FContents) then
  371. FreeAndNil(FContents);
  372. FBorder:=False;
  373. end;
  374. procedure TTableProducer.CreateColumns(FieldList: TStrings);
  375. Var
  376. I : Integer;
  377. FN : String;
  378. begin
  379. For I:=0 to FDataset.FieldCount-1 do
  380. begin
  381. FN:=FDataset.Fields[I].FieldName;
  382. If (FieldList=Nil) or (FieldList.IndexOf(FN)<>-1) then
  383. With FTableColumns.Add as TTableColumn do
  384. begin
  385. FieldName:=FN;
  386. Caption:=FDataset.Fields[i].DisplayName;
  387. end;
  388. end
  389. end;
  390. procedure TTableProducer.CreateColumns(FieldList: String);
  391. Var
  392. L : TStringList;
  393. begin
  394. If (FieldList='') then
  395. CreateColumns(Nil)
  396. else
  397. begin
  398. L:=TStringList.Create;
  399. try
  400. L.CommaText:=FieldList;
  401. CreateColumns(L);
  402. Finally
  403. L.Free;
  404. end;
  405. end;
  406. end;
  407. procedure TTableProducer.CreateTable(Stream: TStream);
  408. begin
  409. If FTableColumns.Count=0 then
  410. CreateColumns(Nil);
  411. BindColumns;
  412. StartTable(Stream);
  413. Try
  414. FCurrentRow:=0;
  415. CreateTableHeader(Stream);
  416. While Not Dataset.EOF do
  417. begin
  418. Inc(FCurrentRow);
  419. CreateTableRow(Stream);
  420. Dataset.Next;
  421. end;
  422. Finally
  423. EndTable(Stream);
  424. FCurrentRow:=-1;
  425. FCurrentCol:=-1;
  426. end;
  427. end;
  428. procedure TTableProducer.CreateTable;
  429. begin
  430. CheckContents;
  431. CreateTable(FContents);
  432. end;
  433. procedure TTableProducer.CreateContent;
  434. begin
  435. CreateTable;
  436. end;
  437. Procedure TTableProducer.SetTableColumns(Value : TTableColumns);
  438. begin
  439. FTableColumns.Assign(Value);
  440. end;
  441. procedure TTableProducer.SetRowAttributes(const AValue: TRowAttributes);
  442. begin
  443. if (FRowAttributes=AValue) then
  444. exit;
  445. FRowAttributes.Assign(AValue);
  446. end;
  447. { TComboBoxProducer }
  448. function TComboBoxProducer.GetInputName: String;
  449. begin
  450. If (FInputName='') then
  451. Result:=Name
  452. else
  453. Result:=FInputName;
  454. end;
  455. constructor TComboBoxProducer.Create(AOwner: TComponent);
  456. begin
  457. inherited Create(AOwner);
  458. end;
  459. destructor TComboBoxProducer.Destroy;
  460. begin
  461. Inherited;
  462. end;
  463. procedure TComboBoxProducer.CreateItem(Stream : TStream; VF,DF : TField; Selected : Boolean);
  464. Const
  465. SOptions : Array[Boolean] of String = ('<OPTION','<OPTION SELECTED');
  466. Var
  467. S : String;
  468. begin
  469. WriteString(STream,SOptions[Selected]);
  470. If (VF<>Nil) and (VF<>DF) then
  471. WriteString(Stream,' VALUE="'+VF.AsString+'"');
  472. WriteString(Stream,'>'+DF.AsString+#10);
  473. end;
  474. procedure TComboBoxProducer.CreateComboBox(Stream: TStream);
  475. Var
  476. VF,DF,SF : TField;
  477. begin
  478. DF:=Dataset.FieldByNAme(DataField);
  479. if (ValueField<>'') then
  480. VF:=Dataset.FieldByName(ValueField)
  481. else
  482. VF:=Nil;
  483. If (Value='') then
  484. SF:=Nil
  485. else
  486. if VF<>NIl then
  487. SF:=VF
  488. else
  489. SF:=DF;
  490. WriteString(Stream,'<SELECT NAME="'+InputName+'">');
  491. Try
  492. While not Dataset.EOF do
  493. begin
  494. CreateItem(Stream,VF,DF,((SF<>Nil) and (SF.AsString=Value)));
  495. Dataset.Next;
  496. end;
  497. Finally
  498. WriteString(Stream,'</SELECT>');
  499. end;
  500. end;
  501. procedure TComboBoxProducer.CreateComboBox;
  502. begin
  503. CheckContents;
  504. CreateComboBox(FContents);
  505. end;
  506. procedure TComboBoxProducer.CreateContent;
  507. begin
  508. CreateComboBox;
  509. end;
  510. { THTMLProceder }
  511. function THTMLProducer.GetContent: String;
  512. begin
  513. If Assigned(FContents) then
  514. begin
  515. SetLength(Result,FContents.Size);
  516. If (FContents.Size>0) then
  517. Move(FContents,Result[1],FContents.Size);
  518. end;
  519. end;
  520. procedure THTMLProducer.CheckContents;
  521. begin
  522. If Assigned(FContents) then
  523. FContents.Clear
  524. else
  525. FContents:=TMemoryStream.Create;
  526. end;
  527. destructor THTMLProducer.Destroy;
  528. begin
  529. If Assigned(FContents) then
  530. FreeAndNil(FContents);
  531. inherited Destroy;
  532. end;
  533. procedure THTMLProducer.ClearContent;
  534. begin
  535. If Assigned(FContents) then
  536. FContents.Clear;
  537. end;
  538. procedure THTMLProducer.WriteString(S: TStream; const Value: String);
  539. Var
  540. L : Integer;
  541. begin
  542. L:=Length(Value);
  543. If L>0 then
  544. S.Write(Value[1],L);
  545. end;
  546. procedure THTMLProducer.WriteString(S: TStream; const Fmt: String;
  547. Args: array of const);
  548. begin
  549. WriteString(S,Format(Fmt,Args));
  550. end;
  551. { TDBHtmlWriter }
  552. function TDBHtmlWriter.CreateTableProducer: TTableProducer;
  553. begin
  554. Result:=TTableProducer.Create(Nil);
  555. end;
  556. procedure TDBHtmlWriter.CreateTable(Dataset: TDataset);
  557. Var
  558. P : TTableProducer;
  559. begin
  560. P:=CreateTableProducer;
  561. Try
  562. CreateTable(Dataset,P);
  563. Finally
  564. P.Free;
  565. end;
  566. end;
  567. procedure TDBHtmlWriter.CreateTable(Dataset: TDataset; Producer: TTableProducer);
  568. begin
  569. Producer.Dataset:=Dataset;
  570. Producer.CreateTable(Self.Stream);
  571. end;
  572. { TRowAttributes }
  573. Procedure TRowAttributes.Assign(Source : TPersistent);
  574. Var
  575. R : TRowAttributes;
  576. begin
  577. If Source is TRowAttributes then
  578. begin
  579. R:=TRowAttributes(Source);
  580. FAlign:=R.FAlign;
  581. FBGColor:=R.FBGColor;
  582. FCustom:=R.FCustom;
  583. FVAlign:=R.FVAlign;
  584. end
  585. else
  586. Inherited Assign(Source)
  587. end;
  588. end.
  589. {
  590. $Log$
  591. Revision 1.6 2003-10-28 08:42:01 michael
  592. + Added ColumnByName method to TTAbleColumns
  593. Revision 1.4 2003/10/03 22:43:17 michael
  594. + Published tablecolumns property in tableproducer
  595. Revision 1.3 2003/10/03 08:42:22 michael
  596. + Form support.
  597. Revision 1.2 2003/10/01 21:07:48 michael
  598. + Added log/header
  599. }