/packages/fpgtk/src/fpglib.pp

https://github.com/slibre/freepascal · Puppet · 240 lines · 212 code · 28 blank · 0 comment · 22 complexity · 7ea3903c985377f1a59ecfcefbd0535c MD5 · raw file

  1. {$mode objfpc}{$h+}
  2. unit FPGlib;
  3. interface
  4. uses classes, glib;
  5. type
  6. TLukForEachProcedure = procedure (item : pointer; data : pointer) of object;
  7. TLList = class (TList)
  8. private
  9. FGSList : PGSList;
  10. FGList : PGList;
  11. FNotUpdating,
  12. FClassesChanged,FSlistChanged,FListChanged : Boolean;
  13. procedure FreeList;
  14. procedure FreeSList;
  15. function CreateGList : PGList;
  16. function GetTheGtkList : PGList;
  17. procedure SetGtkList (Value : PGList);
  18. function CreateGSList : PGSList;
  19. function GetTheGtkSList : PGSlist;
  20. procedure SetGtkSList (Value : PGSList);
  21. procedure BuildFromGtkList;
  22. procedure BuildFromGtkSList;
  23. protected
  24. procedure Notify (Ptr: Pointer; Action: TListNotification); override;
  25. function GetData (index : integer) : pointer; dynamic;
  26. function UngetData (data : pointer) : pointer; dynamic;
  27. // GetData needs to give the pointer to the data in the List or SList of GTK
  28. // UngetData needs to give the item in this list from the datapointer of GTK
  29. public
  30. constructor create;
  31. destructor destroy; override;
  32. function GetGtkList (buffered : boolean) : PGList;
  33. function GetGtkSList (buffered : boolean) : PGSlist;
  34. procedure BeginUpdate; // Currently only changes in 1 list are possible
  35. procedure EndUpdate; // without memory leaks and/or errors in the list
  36. procedure ForEach (Proc : TLukForEachprocedure; data : pointer);
  37. property GtkList : PGList read GetTheGtkList write SetGtkList;
  38. property GtkSList : PGSList read GetTheGtkSList write SetGtkSList;
  39. end;
  40. implementation
  41. { TLList }
  42. procedure TLList.FreeList;
  43. begin
  44. if FGList <> null then
  45. begin
  46. g_list_free (FGList);
  47. FGList := null;
  48. end;
  49. end;
  50. procedure TLList.FreeSList;
  51. begin
  52. if FGSList <> null then
  53. begin
  54. g_slist_free (FGSList);
  55. FGSlist := null;
  56. end;
  57. end;
  58. procedure TLList.Notify(Ptr: Pointer; Action: TListNotification);
  59. begin
  60. inherited;
  61. FClassesChanged := True;
  62. end;
  63. constructor TLList.create;
  64. begin
  65. inherited create;
  66. FClassesChanged := False;
  67. FListChanged := false;
  68. FSListChanged := False;
  69. FGList := null;
  70. FGSList := null;
  71. FNotUpdating := True;
  72. end;
  73. destructor TLList.destroy;
  74. begin
  75. FreeList;
  76. FreeSList;
  77. inherited Destroy;
  78. end;
  79. function TLList.GetGtkList (buffered : boolean) : PGList;
  80. begin
  81. if buffered then
  82. if FClasseschanged then
  83. result := CreateGList
  84. else if FSListChanged then
  85. begin
  86. BuildFromGtkSList;
  87. result := CreateGList;
  88. end
  89. else
  90. result := FGlist
  91. else
  92. result := CreateGList;
  93. end;
  94. function TLList.GetGtkSList (buffered : boolean) : PGSList;
  95. begin
  96. if buffered then
  97. if FClassesChanged then
  98. result := CreateGSList
  99. else if FListChanged then
  100. begin
  101. BuildFromGtkList;
  102. result := CreateGSList;
  103. end
  104. else
  105. result := FGSlist
  106. else
  107. result := CreateGSList;
  108. end;
  109. function TLList.CreateGList : PGList;
  110. var r : integer;
  111. begin
  112. FreeList;
  113. result := null;
  114. for r := pred(count) downto 0 do
  115. result := g_list_prepend (result, GetData(r));
  116. FGList := result;
  117. end;
  118. function TLList.CreateGSList : PGSList;
  119. var r : integer;
  120. begin
  121. FreeSList;
  122. result := null;
  123. for r := pred(count) downto 0 do
  124. result := g_slist_prepend (result, GetData(r));
  125. FGSList := result;
  126. end;
  127. function TLList.GetData (index : integer) : pointer;
  128. begin
  129. result := items[index];
  130. end;
  131. function TLList.UngetData (data : pointer) : pointer;
  132. begin
  133. result := data
  134. end;
  135. function TLList.GetTheGtkList : PGList;
  136. begin
  137. result := GetGtkList (True);
  138. end;
  139. procedure TLList.SetGtkList (Value : PGList);
  140. begin
  141. FGList := Value;
  142. if FNotUpdating then
  143. BuildFromGtkList
  144. else
  145. FListChanged := True;
  146. end;
  147. function TLList.GetTheGtkSList : PGSlist;
  148. begin
  149. result := GetGtkSList (True);
  150. end;
  151. procedure TLList.SetGtkSList (Value : PGSList);
  152. begin
  153. FGSlist := Value;
  154. if FNotUpdating then
  155. BuildFromGtkSList
  156. else
  157. FSListChanged := True;
  158. end;
  159. procedure TLList.BuildFromGtkList;
  160. var p : PGList;
  161. begin
  162. clear;
  163. p := FGList;
  164. while p <> null do
  165. begin
  166. add (UngetData(p^.data));
  167. p := p^.Next;
  168. end;
  169. FListChanged := False;
  170. FSListChanged := False;
  171. FClassesChanged := False;
  172. FreeSList;
  173. end;
  174. procedure TLList.BuildFromGtkSList;
  175. var p :PGSList;
  176. begin
  177. clear;
  178. p := FGSList;
  179. while p <> null do
  180. begin
  181. add (UngetData(p^.data));
  182. p := p^.Next;
  183. end;
  184. FListChanged := False;
  185. FSListChanged := False;
  186. FClassesChanged := False;
  187. FreeList;
  188. end;
  189. procedure TLList.BeginUpdate;
  190. begin
  191. FNotUpdating := False;
  192. end;
  193. procedure TLList.EndUpdate;
  194. begin
  195. FNotUpdating := True;
  196. if FlistChanged then
  197. BuildFromGtkSList
  198. else if FSListChanged then
  199. BuildFromGtkSList
  200. else if FClassesChanged then
  201. begin
  202. FreeSList;
  203. FreeList;
  204. end;
  205. end;
  206. procedure TLList.ForEach (Proc : TLukForEachProcedure; data : pointer);
  207. var r: integer;
  208. begin
  209. for r := 0 to pred(count) do
  210. Proc (items[r], data);
  211. end;
  212. end.