AsphyreClasses.pas
上传用户:ctlcnc
上传日期:2021-12-10
资源大小:4933k
文件大小:10k
源码类别:

2D图形编程

开发平台:

Delphi

  1. unit AsphyreClasses;
  2. //---------------------------------------------------------------------------
  3. // AsphyreClasses.pas                                   Modified: 03-Mar-2007
  4. // Asphyre container class implementation                         Version 1.0
  5. //---------------------------------------------------------------------------
  6. // Important Notice:
  7. //
  8. // If you modify/use this code or one of its parts either in original or
  9. // modified form, you must comply with Mozilla Public License v1.1,
  10. // specifically section 3, "Distribution Obligations". Failure to do so will
  11. // result in the license breach, which will be resolved in the court.
  12. // Remember that violating author's rights is considered a serious crime in
  13. // many countries. Thank you!
  14. //
  15. // !! Please *read* Mozilla Public License 1.1 document located at:
  16. //  http://www.mozilla.org/MPL/
  17. //
  18. // If you require any clarifications about the license, feel free to contact
  19. // us or post your question on our forums at: http://www.afterwarp.net
  20. //---------------------------------------------------------------------------
  21. // The contents of this file are subject to the Mozilla Public License
  22. // Version 1.1 (the "License"); you may not use this file except in
  23. // compliance with the License. You may obtain a copy of the License at
  24. // http://www.mozilla.org/MPL/
  25. //
  26. // Software distributed under the License is distributed on an "AS IS"
  27. // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
  28. // License for the specific language governing rights and limitations
  29. // under the License.
  30. //
  31. // The Original Code is GuiTypes.pas.
  32. //
  33. // The Initial Developer of the Original Code is M. Sc. Yuriy Kotsarenko.
  34. // Portions created by M. Sc. Yuriy Kotsarenko are Copyright (C) 2007,
  35. // Afterwarp Interactive. All Rights Reserved.
  36. //---------------------------------------------------------------------------
  37. interface
  38. //---------------------------------------------------------------------------
  39. uses
  40.  AsphyreUtils;
  41. //---------------------------------------------------------------------------
  42. type
  43.  TAsphyreList = class;
  44. //---------------------------------------------------------------------------
  45.  TAsphyreFreeEvent = procedure(List: TAsphyreList; Item: Pointer) of object;
  46.  TAsphyreSortEvent = function(List: TAsphyreList; Item1,
  47.   Item2: Pointer): Integer of object;
  48.  TAsphyreFindEvent = function(List: TAsphyreList; Item,
  49.   User: Pointer): Integer of object; 
  50. //---------------------------------------------------------------------------
  51.  TAsphyreList = class
  52.  private
  53.   Data     : array of Pointer;
  54.   FCount   : Integer;
  55.   FCapacity: Integer;
  56.   DataDirty: Boolean;
  57.   UserDirty: Boolean;
  58.   DataIndex: array of Integer;
  59.   UserIndex: array of Integer;
  60.   FOnFreeItem: TAsphyreFreeEvent;
  61.   FOnSortItem: TAsphyreSortEvent;
  62.   FOnFindItem: TAsphyreFindEvent;
  63.   procedure SetCapacity(const Value: Integer);
  64.   procedure Grow();
  65.   function GetItems(Index: Integer): Pointer;
  66.   procedure InitDataIndex();
  67.   procedure SortDataIndex(Left, Right: Integer);
  68.   procedure UpdateDataIndex();
  69.   procedure InitUserIndex();
  70.   procedure SortUserIndex(Left, Right: Integer);
  71.   procedure UpdateUserIndex();
  72.  public
  73.   property Capacity: Integer read FCapacity write SetCapacity;
  74.   property Count: Integer read FCount;
  75.   property Items[Index: Integer]: Pointer read GetItems; default;
  76.   // This event should release the item, if necessary.
  77.   property OnFreeItem: TAsphyreFreeEvent read FOnFreeItem write FOnFreeItem;
  78.   // This event should compare two items by custom criteria for sorting.
  79.   property OnSortItem: TAsphyreSortEvent read FOnSortItem write FOnSortItem;
  80.   // This event should compare item with custom criteria for quick search.
  81.   property OnFindItem: TAsphyreFindEvent read FOnFindItem write FOnFindItem;
  82.   function Insert(Item: Pointer): Integer;
  83.   procedure Remove(Index: Integer);
  84.   function IndexOf(Item: Pointer): Integer;
  85.   function FindBy(User: Pointer): Integer;
  86.   procedure Clear();
  87.   constructor Create();
  88.   destructor Destroy(); override;
  89.  end;
  90. //---------------------------------------------------------------------------
  91. implementation
  92. //---------------------------------------------------------------------------
  93. const
  94.  MinGrow  = 4;
  95.  GrowUnit = 8;
  96. //---------------------------------------------------------------------------
  97. constructor TAsphyreList.Create();
  98. begin
  99.  inherited;
  100.  FCount   := 0;
  101.  FCapacity:= 0;
  102.  DataDirty:= False;
  103.  UserDirty:= False;
  104. end;
  105. //---------------------------------------------------------------------------
  106. destructor TAsphyreList.Destroy();
  107. begin
  108.  Clear();
  109.  inherited;
  110. end;
  111. //---------------------------------------------------------------------------
  112. procedure TAsphyreList.SetCapacity(const Value: Integer);
  113. begin
  114.  FCapacity:= Max2(FCount, Value);
  115.  SetLength(Data, FCapacity);
  116.  SetLength(DataIndex, FCapacity);
  117.  SetLength(UserIndex, FCapacity);
  118. end;
  119. //---------------------------------------------------------------------------
  120. procedure TAsphyreList.Grow();
  121. var
  122.  Delta: Integer;
  123. begin
  124.  Delta:= MinGrow + (FCapacity div GrowUnit);
  125.  Inc(FCapacity, Delta);
  126.  SetLength(Data, FCapacity);
  127.  SetLength(DataIndex, FCapacity);
  128.  SetLength(UserIndex, FCapacity);
  129. end;
  130. //---------------------------------------------------------------------------
  131. function TAsphyreList.GetItems(Index: Integer): Pointer;
  132. begin
  133.  if (Index >= 0)and(Index < FCount) then
  134.   Result:= Data[Index] else Result:= nil;
  135. end;
  136. //---------------------------------------------------------------------------
  137. function TAsphyreList.Insert(Item: Pointer): Integer;
  138. begin
  139.  if (FCount >= FCapacity) then Grow();
  140.  Result:= FCount;
  141.  Inc(FCount);
  142.  Data[Result]:= Item;
  143.  DataDirty:= True;
  144.  UserDirty:= True;
  145. end;
  146. //---------------------------------------------------------------------------
  147. procedure TAsphyreList.Remove(Index: Integer);
  148. var
  149.  i: Integer;
  150.  Item: Pointer;
  151. begin
  152.  if (Index < 0)or(Index >= FCount) then Exit;
  153.  Item:= Data[Index];
  154.  for i:= Index to FCount - 2 do
  155.   Data[i]:= Data[i + 1];
  156.  Dec(FCount);
  157.  DataDirty:= True;
  158.  UserDirty:= True;
  159.  if (Assigned(FOnFreeItem)) then FOnFreeItem(Self, Item);
  160. end;
  161. //---------------------------------------------------------------------------
  162. procedure TAsphyreList.Clear();
  163. var
  164.  i: Integer;
  165. begin
  166.  if (not Assigned(FOnFreeItem)) then
  167.   begin
  168.    FCount:= 0;
  169.    SetCapacity(0);
  170.    Exit;
  171.   end;
  172.  for i:= FCount - 1 downto 0 do
  173.   begin
  174.    FOnFreeItem(Self, Data[i]);
  175.    Dec(FCount);
  176.   end;
  177.  SetCapacity(0);
  178. end;
  179. //---------------------------------------------------------------------------
  180. procedure TAsphyreList.InitDataIndex();
  181. var
  182.  i: Integer;
  183. begin
  184.  for i:= 0 to FCount - 1 do
  185.   DataIndex[i]:= i;
  186. end;
  187. //---------------------------------------------------------------------------
  188. procedure TAsphyreList.SortDataIndex(Left, Right: Integer);
  189. var
  190.  Lo, Hi   : Integer;
  191.  TempIndex: Integer;
  192.  MidValue : Integer;
  193. begin
  194.  Lo:= Left;
  195.  Hi:= Right;
  196.  MidValue:= Integer(Data[DataIndex[(Left + Right) div 2]]);
  197.  repeat
  198.   while (Integer(Data[DataIndex[Lo]]) < MidValue) do Inc(Lo);
  199.   while (MidValue < Integer(Data[DataIndex[Hi]])) do Dec(Hi);
  200.   if (Lo <= Hi) then
  201.    begin
  202.     TempIndex:= DataIndex[Lo];
  203.     DataIndex[Lo]:= DataIndex[Hi];
  204.     DataIndex[Hi]:= TempIndex;
  205.     Inc(Lo);
  206.     Dec(Hi);
  207.    end;
  208.  until (Lo > Hi);
  209.  if (Left < Hi) then SortDataIndex(Left, Hi);
  210.  if (Lo < Right) then SortDataIndex(Lo, Right);
  211. end;
  212. //---------------------------------------------------------------------------
  213. procedure TAsphyreList.UpdateDataIndex();
  214. begin
  215.  InitDataIndex();
  216.  if (FCount > 1) then SortDataIndex(0, FCount - 1);
  217.  DataDirty:= False;
  218. end;
  219. //---------------------------------------------------------------------------
  220. function TAsphyreList.IndexOf(Item: Pointer): Integer;
  221. var
  222.  Lo, Hi, Mid: Integer;
  223. begin
  224.  if (DataDirty) then UpdateDataIndex();
  225.  Result:= -1;
  226.  Lo:= 0;
  227.  Hi:= FCount - 1;
  228.  while (Lo <= Hi) do
  229.   begin
  230.    Mid:= (Lo + Hi) div 2;
  231.    if (Data[DataIndex[Mid]] = Item) then
  232.     begin
  233.      Result:= DataIndex[Mid];
  234.      Break;
  235.     end;
  236.    if (Integer(Data[DataIndex[Mid]]) > Integer(Item)) then Hi:= Mid - 1
  237.     else Lo:= Mid + 1;
  238.  end;
  239. end;
  240. //---------------------------------------------------------------------------
  241. procedure TAsphyreList.InitUserIndex();
  242. var
  243.  i: Integer;
  244. begin
  245.  for i:= 0 to FCount - 1 do
  246.   UserIndex[i]:= i;
  247. end;
  248. //---------------------------------------------------------------------------
  249. procedure TAsphyreList.SortUserIndex(Left, Right: Integer);
  250. var
  251.  Lo, Hi   : Integer;
  252.  MidValue : Pointer;
  253.  TempIndex: Integer;
  254. begin
  255.  Lo:= Left;
  256.  Hi:= Right;
  257.  MidValue:= Data[UserIndex[(Left + Right) div 2]];
  258.  repeat
  259.   while (FOnSortItem(Self, Data[UserIndex[Lo]], MidValue) < 0) do Inc(Lo);
  260.   while (FOnSortItem(Self, Data[UserIndex[Hi]], MidValue) > 0) do Dec(Hi);
  261.   if (Lo <= Hi) then
  262.    begin
  263.     TempIndex:= UserIndex[Lo];
  264.     UserIndex[Lo]:= UserIndex[Hi];
  265.     UserIndex[Hi]:= TempIndex;
  266.     Inc(Lo);
  267.     Dec(Hi);
  268.    end;
  269.  until (Lo > Hi);
  270.  if (Left < Hi) then SortUserIndex(Left, Hi);
  271.  if (Lo < Right) then SortUserIndex(Lo, Right);
  272. end;
  273. //---------------------------------------------------------------------------
  274. procedure TAsphyreList.UpdateUserIndex();
  275. begin
  276.  InitUserIndex();
  277.  if (FCount > 1) then SortUserIndex(0, FCount - 1);
  278.  UserDirty:= False;
  279. end;
  280. //---------------------------------------------------------------------------
  281. function TAsphyreList.FindBy(User: Pointer): Integer;
  282. var
  283.  Lo, Hi, Mid: Integer;
  284. begin
  285.  if (UserDirty) then UpdateUserIndex();
  286.  Result:= -1;
  287.  Lo:= 0;
  288.  Hi:= FCount - 1;
  289.  while (Lo <= Hi) do
  290.   begin
  291.    Mid:= (Lo + Hi) div 2;
  292.    if (FOnFindItem(Self, Data[UserIndex[Mid]], User) = 0) then
  293.     begin
  294.      Result:= UserIndex[Mid];
  295.      Break;
  296.     end;
  297.    if (FOnFindItem(Self, Data[UserIndex[Mid]], User) > 0) then Hi:= Mid - 1
  298.     else Lo:= Mid + 1;
  299.  end;
  300. end;
  301. //---------------------------------------------------------------------------
  302. end.