Advertisement
Guest User

Untitled

a guest
Aug 23rd, 2017
63
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.22 KB | None | 0 0
  1. unit UDebouncedEvent;
  2.  
  3. interface
  4.  
  5. uses
  6. System.Classes, System.SysUtils, System.DateUtils, FMX.Types;
  7.  
  8. type
  9. TDebouncedEvent = class (TComponent)
  10. private
  11. FSourceEvent: TNotifyEvent;
  12. FInterval: integer;
  13.  
  14. FTimer: TTimer;
  15. FSender: TObject;
  16.  
  17. FLastcallTimestamp: TDateTime;
  18.  
  19. procedure DebouncedEvent(Sender: TObject);
  20.  
  21. procedure DoCallEvent(Sender: TObject);
  22. procedure DoOnTimer(Sender: TObject);
  23. protected
  24. constructor Create(AOwner: TComponent; ASourceEvent: TNotifyEvent;
  25. AInterval: integer); reintroduce;
  26. public
  27. class function Wrap(ASourceEvent: TNotifyEvent; AInterval: integer;
  28. AOwner: TComponent): TNotifyEvent;
  29. end;
  30.  
  31. implementation
  32.  
  33. { TDebouncedEvent }
  34.  
  35. constructor TDebouncedEvent.Create(AOwner: TComponent;
  36. ASourceEvent: TNotifyEvent; AInterval: integer);
  37. begin
  38. inherited Create(AOwner);
  39. self.FSourceEvent := ASourceEvent;
  40. self.FInterval := AInterval;
  41.  
  42. self.FTimer := TTimer.Create(self);
  43. self.FTimer.Enabled := false;
  44. self.FTimer.Interval := AInterval;
  45. self.FTimer.OnTimer := self.DoOnTimer;
  46. end;
  47.  
  48. procedure TDebouncedEvent.DebouncedEvent(Sender: TObject);
  49. var
  50. Between: int64;
  51. begin
  52. Between := MilliSecondsBetween(Now, self.FLastcallTimestamp);
  53.  
  54. // if timer is not enabled, it means that last call happened
  55. // earlier than <self.FInteval> milliseconds ago
  56. if Between >= self.FInterval then begin
  57. self.DoCallEvent(Sender);
  58. end
  59. else begin
  60. // adjusting timer, so interval between calls will never be more than <FInterval> ms
  61. self.FTimer.Interval := self.FInterval - Between;
  62.  
  63. // reset the timer
  64. self.FTimer.Enabled := false;
  65. self.FTimer.Enabled := true;
  66.  
  67. // remember last Sender argument value to use it in a delayed call
  68. self.FSender := Sender;
  69. end;
  70. end;
  71.  
  72. procedure TDebouncedEvent.DoCallEvent(Sender: TObject);
  73. begin
  74. self.FLastcallTimestamp := Now;
  75. self.FSourceEvent(Sender);
  76. end;
  77.  
  78. procedure TDebouncedEvent.DoOnTimer(Sender: TObject);
  79. begin
  80. self.FTimer.Enabled := false;
  81. self.DoCallEvent(self.FSender);
  82. end;
  83.  
  84. class function TDebouncedEvent.Wrap(ASourceEvent: TNotifyEvent;
  85. AInterval: integer; AOwner: TComponent): TNotifyEvent;
  86. begin
  87. Result := TDebouncedEvent.Create(AOwner, ASourceEvent, AInterval).DebouncedEvent;
  88. end;
  89.  
  90. end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement