2
0

datasource.inc 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577
  1. { ---------------------------------------------------------------------
  2. TDatalink
  3. ---------------------------------------------------------------------}
  4. Constructor TDataLink.Create;
  5. begin
  6. Inherited Create;
  7. FBufferCount:=1;
  8. FDataSource := nil;
  9. FDatasourceFixed:=False;
  10. end;
  11. Destructor TDataLink.Destroy;
  12. begin
  13. Factive:=False;
  14. FEditing:=False;
  15. FDataSourceFixed:=False;
  16. DataSource:=Nil;
  17. Inherited Destroy;
  18. end;
  19. Procedure TDataLink.ActiveChanged;
  20. begin
  21. end;
  22. Procedure TDataLink.CheckActiveAndEditing;
  23. Var
  24. B : Boolean;
  25. begin
  26. B:=Assigned(DataSource) and (DataSource.State<>dsInactive);
  27. If B<>FActive then
  28. begin
  29. FActive:=B;
  30. ActiveChanged;
  31. end;
  32. B:=Assigned(DataSource) and (DataSource.State in dsEditModes) and Not FReadOnly;
  33. If B<>FEditing Then
  34. begin
  35. FEditing:=B;
  36. EditingChanged;
  37. end;
  38. end;
  39. Procedure TDataLink.CheckBrowseMode;
  40. begin
  41. end;
  42. Function TDataLink.CalcFirstRecord(Index : Integer) : Integer;
  43. { recalculates index of first record in buffer,
  44. and returns number of record scrolled.}
  45. Var
  46. A, // Index of active record in buffer
  47. F, // Index of current first record in buffer
  48. L : Integer; // index of Last (for us) record in buffer;
  49. begin
  50. Result:=0;
  51. A:=DataSource.DataSet.FActiveRecord;
  52. F:=FFirstRecord+Index;
  53. L:=F+FBufferCount-1;
  54. If A>L Then
  55. Result:=A-L
  56. else If A<F Then
  57. Result:=A-F;
  58. FFirstRecord:=F+Result;
  59. {$IfDef dsDebug}
  60. WriteLn('CalcFirstRecord: FFirstRecord=',FFirstRecord,' Scrolled=',Result);
  61. {$Endif}
  62. end;
  63. Procedure TDataLink.CalcRange;
  64. var
  65. aMax, aMin: integer;
  66. begin
  67. aMin:= DataSet.FActiveRecord - FBufferCount + 1;
  68. If aMin < 0 Then aMin:= 0;
  69. aMax:= Dataset.FBufferCount - FBufferCount;
  70. If aMax < 0 then aMax:= 0;
  71. If aMax>DataSet.FActiveRecord Then aMax:=DataSet.FActiveRecord;
  72. If FFirstRecord < aMin Then FFirstRecord:= aMin;
  73. If FFirstrecord > aMax Then FFirstRecord:= aMax;
  74. If (FfirstRecord<>0) And
  75. (DataSet.FActiveRecord - FFirstRecord < FBufferCount -1) Then
  76. Dec(FFirstRecord, 1);
  77. end;
  78. Procedure TDataLink.DataEvent(Event: TDataEvent; Info: Ptrint);
  79. begin
  80. Case Event of
  81. deFieldChange, deRecordChange:
  82. If Not FUpdatingRecord then
  83. RecordChanged(TField(Info));
  84. deDataSetChange: begin
  85. SetActive(DataSource.DataSet.Active);
  86. CalcFirstRecord(Info);
  87. DatasetChanged;
  88. end;
  89. deDataSetScroll: DatasetScrolled(CalcFirstRecord(Info));
  90. deLayoutChange: begin
  91. CalcFirstRecord(Info);
  92. LayoutChanged;
  93. end;
  94. deUpdateRecord: UpdateRecord;
  95. deUpdateState: CheckActiveAndEditing;
  96. deCheckBrowseMode: CheckBrowseMode;
  97. deFocusControl: FocusControl(TFieldRef(Info));
  98. end;
  99. end;
  100. Procedure TDataLink.DataSetChanged;
  101. begin
  102. RecordChanged(Nil);
  103. end;
  104. Procedure TDataLink.DataSetScrolled(Distance: Integer);
  105. begin
  106. DataSetChanged;
  107. end;
  108. Procedure TDataLink.EditingChanged;
  109. begin
  110. end;
  111. Procedure TDataLink.FocusControl(Field: TFieldRef);
  112. begin
  113. end;
  114. Function TDataLink.GetActiveRecord: Integer;
  115. begin
  116. Result:=Dataset.FActiveRecord - FFirstRecord;
  117. end;
  118. Function TDatalink.GetDataSet : TDataset;
  119. begin
  120. Result:=FDataSource.DataSet
  121. end;
  122. Function TDataLink.GetBOF: Boolean;
  123. begin
  124. Result:=DataSet.BOF
  125. end;
  126. Function TDataLink.GetBufferCount: Integer;
  127. begin
  128. Result:=FBufferCount;
  129. end;
  130. Function TDataLink.GetEOF: Boolean;
  131. begin
  132. Result:=DataSet.EOF
  133. end;
  134. Function TDataLink.GetRecordCount: Integer;
  135. Var D: TDataSet;
  136. begin
  137. Result:=Dataset.FRecordCount;
  138. If Result>BufferCount then
  139. Result:=BufferCount;
  140. end;
  141. Procedure TDataLink.LayoutChanged;
  142. begin
  143. DataSetChanged;
  144. end;
  145. Function TDataLink.MoveBy(Distance: Integer): Integer;
  146. begin
  147. Result:=DataSet.MoveBy(Distance);
  148. end;
  149. Procedure TDataLink.RecordChanged(Field: TField);
  150. begin
  151. end;
  152. Procedure TDataLink.SetActiveRecord(Value: Integer);
  153. begin
  154. {$ifdef dsdebug}
  155. Writeln('Datalink. Setting active record to ',Value,' with firstrecord ',ffirstrecord);
  156. {$endif}
  157. Dataset.FActiveRecord:=Value + FFirstRecord;
  158. end;
  159. Procedure TDataLink.SetBufferCount(Value: Integer);
  160. begin
  161. If FBufferCount<>Value then
  162. begin
  163. FBufferCount:=Value;
  164. if Active then begin
  165. DataSet.RecalcBufListSize;
  166. CalcRange;
  167. end;
  168. end;
  169. end;
  170. procedure TDataLink.SetActive(AActive: Boolean);
  171. begin
  172. if Active <> AActive then
  173. begin
  174. FActive := AActive;
  175. // !!!: Set internal state
  176. ActiveChanged;
  177. end;
  178. end;
  179. Procedure TDataLink.SetDataSource(Value : TDatasource);
  180. begin
  181. if not FDataSourceFixed then
  182. begin
  183. if Assigned(DataSource) then
  184. Begin
  185. DataSource.UnregisterDatalink(Self);
  186. FDataSource := nil;
  187. CheckActiveAndEditing;
  188. End;
  189. FDataSource := Value;
  190. if Assigned(DataSource) then
  191. begin
  192. DataSource.RegisterDatalink(Self);
  193. CheckActiveAndEditing;
  194. End;
  195. end;
  196. end;
  197. Procedure TDatalink.SetReadOnly(Value : Boolean);
  198. begin
  199. If FReadOnly<>Value then
  200. begin
  201. FReadOnly:=Value;
  202. CheckActiveAndEditing;
  203. end;
  204. end;
  205. Procedure TDataLink.UpdateData;
  206. begin
  207. end;
  208. Function TDataLink.Edit: Boolean;
  209. begin
  210. If Not FReadOnly then
  211. DataSource.Edit;
  212. // Triggered event will set FEditing
  213. Result:=FEditing;
  214. end;
  215. Procedure TDataLink.UpdateRecord;
  216. begin
  217. FUpdatingRecord:=True;
  218. Try
  219. UpdateData;
  220. finally
  221. FUpdatingRecord:=False;
  222. end;
  223. end;
  224. { ---------------------------------------------------------------------
  225. TDetailDataLink
  226. ---------------------------------------------------------------------}
  227. Function TDetailDataLink.GetDetailDataSet: TDataSet;
  228. begin
  229. Result := nil;
  230. end;
  231. { ---------------------------------------------------------------------
  232. TMasterDataLink
  233. ---------------------------------------------------------------------}
  234. constructor TMasterDataLink.Create(ADataSet: TDataSet);
  235. begin
  236. inherited Create;
  237. FDataSet := ADataSet;
  238. FFields := TList.Create;
  239. end;
  240. destructor TMasterDataLink.Destroy;
  241. begin
  242. FFields.Free;
  243. inherited Destroy;
  244. end;
  245. Procedure TMasterDataLink.ActiveChanged;
  246. begin
  247. FFields.Clear;
  248. if Active then
  249. try
  250. DataSet.GetFieldList(FFields, FFieldNames);
  251. except
  252. FFields.Clear;
  253. raise;
  254. end;
  255. if FDataSet.Active and not (csDestroying in FDataSet.ComponentState) then
  256. if Active and (FFields.Count > 0) then
  257. begin
  258. if Assigned(FOnMasterChange) then FOnMasterChange(Self);
  259. end else
  260. if Assigned(FOnMasterDisable) then FOnMasterDisable(Self);
  261. end;
  262. Procedure TMasterDataLink.CheckBrowseMode;
  263. begin
  264. if FDataSet.Active then FDataSet.CheckBrowseMode;
  265. end;
  266. Function TMasterDataLink.GetDetailDataSet: TDataSet;
  267. begin
  268. Result := FDataSet;
  269. end;
  270. Procedure TMasterDataLink.LayoutChanged;
  271. begin
  272. ActiveChanged;
  273. end;
  274. Procedure TMasterDataLink.RecordChanged(Field: TField);
  275. begin
  276. if (DataSource.State <> dsSetKey) and FDataSet.Active and
  277. (FFields.Count > 0) and ((Field = nil) or
  278. (FFields.IndexOf(Field) >= 0)) and
  279. Assigned(FOnMasterChange) then
  280. FOnMasterChange(Self);
  281. end;
  282. procedure TMasterDatalink.SetFieldNames(const Value: string);
  283. begin
  284. if FFieldNames <> Value then
  285. begin
  286. FFieldNames := Value;
  287. ActiveChanged;
  288. end;
  289. end;
  290. { ---------------------------------------------------------------------
  291. TDatasource
  292. ---------------------------------------------------------------------}
  293. Constructor TDataSource.Create(AOwner: TComponent);
  294. begin
  295. Inherited Create(AOwner);
  296. FDatalinks := TList.Create;
  297. FEnabled := True;
  298. FAutoEdit := True;
  299. end;
  300. Destructor TDataSource.Destroy;
  301. begin
  302. FOnStateCHange:=Nil;
  303. Dataset:=Nil;
  304. With FDataLinks do
  305. While Count>0 do
  306. TDatalink(Items[Count - 1]).DataSource:=Nil;
  307. FDatalinks.Free;
  308. inherited Destroy;
  309. end;
  310. Procedure TDatasource.Edit;
  311. begin
  312. If (State=dsBrowse) and AutoEdit Then
  313. Dataset.Edit;
  314. end;
  315. Function TDataSource.IsLinkedTo(ADataSet: TDataSet): Boolean;
  316. begin
  317. Result:=False;
  318. end;
  319. procedure TDatasource.DistributeEvent(Event: TDataEvent; Info: Ptrint);
  320. Var
  321. i : Longint;
  322. begin
  323. With FDatalinks do
  324. begin
  325. For I:=0 to Count-1 do
  326. With TDatalink(Items[i]) do
  327. If Not VisualControl Then
  328. DataEvent(Event,Info);
  329. For I:=0 to Count-1 do
  330. With TDatalink(Items[i]) do
  331. If VisualControl Then
  332. DataEvent(Event,Info);
  333. end;
  334. end;
  335. procedure TDatasource.RegisterDataLink(DataLink: TDataLink);
  336. begin
  337. FDatalinks.Add(DataLink);
  338. if Assigned(DataSet) then
  339. DataSet.RecalcBufListSize;
  340. end;
  341. procedure TDatasource.SetDataSet(ADataSet: TDataSet);
  342. begin
  343. If FDataset<>Nil Then
  344. Begin
  345. FDataset.UnRegisterDataSource(Self);
  346. FDataSet:=nil;
  347. ProcessEvent(deUpdateState,0);
  348. End;
  349. If ADataset<>Nil Then
  350. begin
  351. ADataset.RegisterDatasource(Self);
  352. FDataSet:=ADataset;
  353. ProcessEvent(deUpdateState,0);
  354. End;
  355. end;
  356. procedure TDatasource.SetEnabled(Value: Boolean);
  357. begin
  358. FEnabled:=Value;
  359. end;
  360. Procedure TDatasource.DoDataChange (Info : Pointer);
  361. begin
  362. If Assigned(OnDataChange) Then
  363. OnDataChange(Self,TField(Info));
  364. end;
  365. Procedure TDatasource.DoStateChange;
  366. begin
  367. If Assigned(OnStateChange) Then
  368. OnStateChange(Self);
  369. end;
  370. Procedure TDatasource.DoUpdateData;
  371. begin
  372. If Assigned(OnUpdateData) Then
  373. OnUpdateData(Self);
  374. end;
  375. procedure TDatasource.UnregisterDataLink(DataLink: TDataLink);
  376. begin
  377. FDatalinks.Remove(Datalink);
  378. If Dataset<>Nil then
  379. DataSet.RecalcBufListSize;
  380. //Dataset.SetBufListSize(DataLink.BufferCount);
  381. end;
  382. procedure TDataSource.ProcessEvent(Event : TDataEvent; Info : Ptrint);
  383. Const
  384. OnDataChangeEvents = [deRecordChange, deDataSetChange, deDataSetScroll,
  385. deLayoutChange,deUpdateState];
  386. Var
  387. NeedDataChange : Boolean;
  388. FLastState : TdataSetState;
  389. begin
  390. // Special UpdateState handling.
  391. If Event=deUpdateState then
  392. begin
  393. NeedDataChange:=(FState=dsInactive);
  394. FLastState:=FState;
  395. If Assigned(Dataset) then
  396. FState:=Dataset.State
  397. else
  398. FState:=dsInactive;
  399. // Don't do events if nothing changed.
  400. If FState=FlastState then
  401. exit;
  402. end
  403. else
  404. NeedDataChange:=True;
  405. DistributeEvent(Event,Info);
  406. // Extra handlers
  407. If Not (csDestroying in ComponentState) then
  408. begin
  409. If (Event=deUpdateState) then
  410. DoStateChange;
  411. If (Event in OnDataChangeEvents) and
  412. NeedDataChange Then
  413. DoDataChange(Nil);
  414. If (Event = deFieldChange) Then
  415. DoDataCHange(Pointer(Info));
  416. If (Event=deUpdateRecord) then
  417. DoUpdateData;
  418. end;
  419. end;