You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

370 line
16 KiB

  1. unit uutlObservableGenerics;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5. Classes, SysUtils,
  6. uutlGenerics, uutlInterfaces;
  7. type
  8. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  9. generic TutlEventList<T> = class(specialize TutlHashSetBase<T>)
  10. private type
  11. TComparer = class(TInterfacedObject, IComparer)
  12. public
  13. function Compare(const i1, i2: T): Integer;
  14. end;
  15. public
  16. function RegisterEvent(const aEvent: T): Boolean;
  17. function UnregisterEvent(const aEvent: T): Boolean;
  18. constructor Create;
  19. end;
  20. TutlNotifyEventList = specialize TutlEventList<TNotifyEvent>;
  21. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  22. generic TutlObservableCustomList<T> = class(specialize TutlCustomList<T>)
  23. public type
  24. TEventList = specialize TutlEventList<TItemEvent>;
  25. private
  26. fOnAddItem: TEventList;
  27. fOnRemoveItem: TEventList;
  28. protected
  29. procedure InsertIntern(const aIndex: Integer; const aItem: T); override;
  30. procedure DeleteIntern(const aIndex: Integer; const aFreeItem: Boolean = true); override;
  31. procedure DoAddItem(const aIndex: Integer; const aItem: T); virtual;
  32. procedure DoRemoveItem(const aIndex: Integer; const aItem: T); virtual;
  33. public
  34. property OnAddItem: TEventList read fOnAddItem;
  35. property OnRemoveItem: TEventList read fOnRemoveItem;
  36. constructor Create(aEqualityComparer: IEqualityComparer; const aOwnsObjects: Boolean = true);
  37. destructor Destroy; override;
  38. end;
  39. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  40. generic TutlObservableList<T> = class(specialize TutlObservableCustomList<T>)
  41. public type
  42. TEqualityComparer = specialize TutlEqualityComparer<T>;
  43. public
  44. constructor Create(const aOwnsObjects: Boolean = true);
  45. end;
  46. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  47. generic TutlObservableCustomHashSet<T> = class(specialize TutlCustomHashSet<T>)
  48. public type
  49. TEventList = specialize TutlEventList<THashItemEvent>;
  50. private
  51. fOnAddItem: TEventList;
  52. fOnRemoveItem: TEventList;
  53. protected
  54. procedure InsertIntern(const aIndex: Integer; const aItem: T); override;
  55. procedure DeleteIntern(const aIndex: Integer; const aFreeItem: Boolean = true); override;
  56. procedure DoAddItem(const aItem: T); virtual;
  57. procedure DoRemoveItem(const aItem: T); virtual;
  58. public
  59. property OnAddItem: TEventList read fOnAddItem;
  60. property OnRemoveItem: TEventList read fOnRemoveItem;
  61. constructor Create(aComparer: IComparer; const aOwnsObjects: Boolean = true);
  62. destructor Destroy; override;
  63. end;
  64. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  65. generic TutlObservableHashSet<T> = class(specialize TutlObservableCustomHashSet<T>)
  66. public type
  67. TComparer = specialize TutlComparer<T>;
  68. public
  69. constructor Create(const aOwnsObjects: Boolean = true);
  70. end;
  71. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  72. generic TutlObservableCustomMap<TKey, TValue> = class(specialize TutlMapBase<TKey, TValue>)
  73. public type
  74. TEventList = specialize TutlEventList<TKeyValuePairEvent>;
  75. TObservableHashSet = class(THashSet)
  76. private
  77. fOwner: TutlObservableCustomMap;
  78. protected
  79. procedure InsertIntern(const aIndex: Integer; const aItem: TKeyValuePair); override;
  80. procedure DeleteIntern(const aIndex: Integer; const aFreeItem: Boolean = true); override;
  81. public
  82. constructor Create(const aOwner: TutlObservableCustomMap; const aComparer: IComparer; const aOwnsObjects: Boolean = true);
  83. end;
  84. private
  85. fHashSetImpl: TObservableHashSet;
  86. fOnAddItem: TEventList;
  87. fOnRemoveItem: TEventList;
  88. protected
  89. procedure DoAddItem(const aKey: TKey; const aValue: TValue); virtual;
  90. procedure DoRemoveItem(const aKey: TKey; const aValue: TValue); virtual;
  91. public
  92. property OnAddItem: TEventList read fOnAddItem;
  93. property OnRemoveItem: TEventList read fOnRemoveItem;
  94. constructor Create(const aComparer: IComparer; const aOwnsObjects: Boolean = true);
  95. destructor Destroy; override;
  96. end;
  97. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  98. generic TutlObservableMap<TKey, TValue> = class(specialize TutlObservableCustomMap<TKey, TValue>)
  99. public type
  100. TComparer = specialize TutlComparer<TKey>;
  101. public
  102. constructor Create(const aOwnsObjects: Boolean = true);
  103. end;
  104. implementation
  105. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  106. //TutlEventList/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  107. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  108. function TutlEventList.TComparer.Compare(const i1, i2: T): Integer;
  109. var
  110. m1, m2: TMethod;
  111. begin
  112. m1 := TMethod(i1);
  113. m2 := TMethod(i2);
  114. if (m1.Data < m2.Data) then
  115. result := -1
  116. else if (m1.Data > m2.Data) then
  117. result := 1
  118. else if (m1.Code < m2.Code) then
  119. result := -1
  120. else if (m1.Code > m2.Code) then
  121. result := 1
  122. else
  123. result := 0;
  124. end;
  125. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  126. function TutlEventList.RegisterEvent(const aEvent: T): Boolean;
  127. var
  128. i: Integer;
  129. begin
  130. result := (SearchItem(0, List.Count-1, aEvent, i) < 0);
  131. if result then
  132. InsertIntern(i, aEvent);
  133. end;
  134. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  135. function TutlEventList.UnregisterEvent(const aEvent: T): Boolean;
  136. var
  137. i, tmp: Integer;
  138. begin
  139. i := SearchItem(0, List.Count-1, aEvent, tmp);
  140. result := (i >= 0);
  141. if result then
  142. DeleteIntern(i);
  143. end;
  144. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  145. constructor TutlEventList.Create;
  146. begin
  147. inherited Create(TComparer.Create, true);
  148. end;
  149. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  150. //TutlObservableCustomList//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  151. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  152. procedure TutlObservableCustomList.InsertIntern(const aIndex: Integer; const aItem: T);
  153. begin
  154. inherited InsertIntern(aIndex, aItem);
  155. DoAddItem(aIndex, aItem);
  156. end;
  157. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  158. procedure TutlObservableCustomList.DeleteIntern(const aIndex: Integer; const aFreeItem: Boolean);
  159. begin
  160. DoRemoveItem(aIndex, aIndex);
  161. inherited DeleteIntern(aIndex, aFreeItem);
  162. end;
  163. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  164. procedure TutlObservableCustomList.DoAddItem(const aIndex: Integer; const aItem: T);
  165. var
  166. e: TItemEvent;
  167. begin
  168. if Assigned(fOnAddItem) then
  169. for e in fOnAddItem do
  170. e(self, aIndex, aItem);
  171. end;
  172. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  173. procedure TutlObservableCustomList.DoRemoveItem(const aIndex: Integer; const aItem: T);
  174. var
  175. e: TItemEvent;
  176. begin
  177. if Assigned(fOnRemoveItem) then
  178. for e in fOnRemoveItem do
  179. e(self, aIndex, GetItem(aIndex));
  180. end;
  181. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  182. constructor TutlObservableCustomList.Create(aEqualityComparer: IEqualityComparer; const aOwnsObjects: Boolean);
  183. begin
  184. inherited Create(aEqualityComparer, aOwnsObjects);
  185. fOnAddItem := TEventList.Create;
  186. fOnRemoveItem := TEventList.Create;
  187. end;
  188. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  189. destructor TutlObservableCustomList.Destroy;
  190. begin
  191. FreeAndNil(fOnRemoveItem);
  192. FreeAndNil(fOnAddItem);
  193. inherited Destroy;
  194. end;
  195. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  196. //TutlObservableList////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  197. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  198. constructor TutlObservableList.Create(const aOwnsObjects: Boolean);
  199. begin
  200. inherited Create(TEqualityComparer.Create, aOwnsObjects);
  201. end;
  202. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  203. //TutlObservableCustomHashSet///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  204. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  205. procedure TutlObservableCustomHashSet.InsertIntern(const aIndex: Integer; const aItem: T);
  206. begin
  207. inherited InsertIntern(aIndex, aItem);
  208. DoAddItem(aItem);
  209. end;
  210. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  211. procedure TutlObservableCustomHashSet.DeleteIntern(const aIndex: Integer; const aFreeItem: Boolean);
  212. begin
  213. DoRemoveItem(GetItem(aIndex));
  214. inherited DeleteIntern(aIndex, aFreeItem);
  215. end;
  216. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  217. procedure TutlObservableCustomHashSet.DoAddItem(const aItem: T);
  218. var
  219. e: THashItemEvent;
  220. begin
  221. if Assigned(fOnAddItem) then
  222. for e in fOnAddItem do
  223. e(self, aItem);
  224. end;
  225. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  226. procedure TutlObservableCustomHashSet.DoRemoveItem(const aItem: T);
  227. var
  228. e: THashItemEvent;
  229. begin
  230. if Assigned(fOnRemoveItem) then
  231. for e in fOnRemoveItem do
  232. e(self, aItem);
  233. end;
  234. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  235. constructor TutlObservableCustomHashSet.Create(aComparer: IComparer; const aOwnsObjects: Boolean);
  236. begin
  237. inherited Create(aComparer, aOwnsObjects);
  238. fOnAddItem := TEventList.Create;
  239. fOnRemoveItem := TEventList.Create;
  240. end;
  241. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  242. destructor TutlObservableCustomHashSet.Destroy;
  243. begin
  244. inherited Destroy; // calls clear -> Free EventLists after
  245. FreeAndNil(fOnAddItem);
  246. FreeAndNil(fOnRemoveItem);
  247. end;
  248. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  249. //TutlObservableHashSet/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  250. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  251. constructor TutlObservableHashSet.Create(const aOwnsObjects: Boolean);
  252. begin
  253. inherited Create(TComparer.Create, aOwnsObjects);
  254. end;
  255. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  256. //TutlObservableCustomMap///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  257. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  258. procedure TutlObservableCustomMap.TObservableHashSet.InsertIntern(const aIndex: Integer; const aItem: TKeyValuePair);
  259. begin
  260. inherited InsertIntern(aIndex, aItem);
  261. fOwner.DoAddItem(aItem.Key, aItem.Value);
  262. end;
  263. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  264. procedure TutlObservableCustomMap.TObservableHashSet.DeleteIntern(const aIndex: Integer; const aFreeItem: Boolean);
  265. var
  266. kvp: TKeyValuePair;
  267. begin
  268. kvp := GetItem(aIndex);
  269. fOwner.DoRemoveItem(kvp.Key, kvp.Value);
  270. inherited DeleteIntern(aIndex, aFreeItem);
  271. end;
  272. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  273. constructor TutlObservableCustomMap.TObservableHashSet.Create(
  274. const aOwner: TutlObservableCustomMap; const aComparer: IComparer; const aOwnsObjects: Boolean);
  275. begin
  276. inherited Create(aComparer, aOwnsObjects);
  277. fOwner := aOwner;
  278. end;
  279. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  280. procedure TutlObservableCustomMap.DoAddItem(const aKey: TKey; const aValue: TValue);
  281. var
  282. e: TKeyValuePairEvent;
  283. begin
  284. if not Assigned(fOnAddItem) then
  285. exit;
  286. for e in fOnAddItem do
  287. e(self, aKey, aValue);
  288. end;
  289. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  290. procedure TutlObservableCustomMap.DoRemoveItem(const aKey: TKey; const aValue: TValue);
  291. var
  292. e: TKeyValuePairEvent;
  293. begin
  294. if not Assigned(fOnRemoveItem) then
  295. exit;
  296. for e in fOnRemoveItem do
  297. e(self, aKey, aValue);
  298. end;
  299. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  300. constructor TutlObservableCustomMap.Create(const aComparer: IComparer; const aOwnsObjects: Boolean);
  301. begin
  302. fOnAddItem := TEventList.Create;
  303. fOnRemoveItem := TEventList.Create;
  304. fHashSetImpl := TObservableHashSet.Create(self, TKeyValuePairComparer.Create(aComparer), aOwnsObjects);
  305. inherited Create(fHashSetImpl);
  306. end;
  307. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  308. destructor TutlObservableCustomMap.Destroy;
  309. begin
  310. inherited Destroy;
  311. FreeAndNil(fHashSetImpl);
  312. FreeAndNil(fOnAddItem);
  313. FreeAndNil(fOnRemoveItem);
  314. end;
  315. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  316. //TutlObservableMap/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  317. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  318. constructor TutlObservableMap.Create(const aOwnsObjects: Boolean);
  319. begin
  320. inherited Create(TComparer.Create, aOwnsObjects);
  321. end;
  322. end.