1+ classdef EventDebouncer < handle
2+ % EventDebouncer
3+ %
4+ % Very useful for limiting the number of times a callback is executed. For
5+ % example when listening to markedClean events on graphics objects.
6+ %
7+ % debounce = EventDebouncer(1); %Throttle to 1s
8+ % for i = 1:10
9+ % debounce(@() disp(i));
10+ % pause(.2);
11+ % end
12+ %
13+ % Can debounce any number of function handles. debounce(@f1,@f2,@f3...);
14+ % Can be default constructed for 100ms.
15+ %
16+ % For an explination of what debounce vs. throttling does see:
17+ % https://redd.one/blog/debounce-vs-throttle
18+ %
19+ properties (SetObservable )
20+ delay (1 ,1 ) double ; % Secconds
21+ end
22+ properties (Access = private )
23+ time (1 ,1 ) timer ;
24+ functionList ;
25+ end
26+ methods
27+ function this = EventDebouncer(delay )
28+ arguments
29+ delay (1 ,1 ) double = .1 ;
30+ end
31+ this.delay = delay ;
32+ this.time = timer(...
33+ " StartDelay" , this .delay ,...
34+ " TimerFcn" , @(~,~) this .callFcns());
35+
36+ this .addlistener(" delay" , " PostSet" , @(~,~) this .updateTimerDelay());
37+ end
38+ function subsref(this ,ref )
39+ for i = 1 : numel(ref .subs )
40+ if ~isa(ref.subs{i }, " function_handle" )
41+ error(" throttleCalls:MustBeFcnHandle" , " Must call with a function handle" );
42+ end
43+ end
44+ if this .time .Running
45+ this .time .stop();
46+ end
47+ this.functionList = ref .subs ;
48+ this .time .start();
49+ end
50+ function delete(this )
51+ this .time .stop();
52+ delete(this .time );
53+ end
54+ end
55+ methods (Access = private )
56+ function callFcns(this )
57+ for i = 1 : numel(this .functionList )
58+ this.functionList{i }();
59+ end
60+ end
61+ function updateTimerDelay(this )
62+ this.time.StartDelay = this .delay ;
63+ end
64+ end
65+ end
0 commit comments