Patrick Happel
Patrick Happel

Reputation: 1351

Triggering and listening to an event

I have a class that represent some data and a (short) chain of results originating from this data. The class has the three properties Data1, Data2 and Data3, where Data2 depends on Data1 (it is actually a filtered version of it) and Data3 depends on Data2.

My idea was to trigger an event when Data1 changes that computes Data2, and then trigger an other event that leads to the computation of Data3. However, in the test class below, Data3 is empty after construction.

Note that I use uiw.event.EventData from the Widget toolbox.

classdef test < handle
    events
        DataChanged 
    end

    properties
        DataChangedListener event.listener
    end

    properties (AbortSet)
        Data1 (:,:) double = []
        Data2 (:,:) double = []
        Data3 (:,:) double = []
    end


    methods
        function self = test()
            self.DataChangedListener = event.listener(self, 'DataChanged', @self.onDataChanged);
            self.Data1 = peaks(64);
        end

        %% setter

        function set.Data1(self, d)
            self.Data1 = d;
            evt = uiw.event.EventData( ...
                'EventType', 'DataChanged', ...
                'Property', 'Data1', ...
                'Model', self );
            self.notify('DataChanged', evt);
        end
        function set.Data2(self, d)
            self.Data2 = d;
            evt = uiw.event.EventData( ...
                'EventType', 'DataChanged', ...
                'Property', 'Data2', ...
                'Model', self );
            self.notify('DataChanged', evt);
        end
        function set.Data3(self, d)
            self.Data3 = d;
            evt = uiw.event.EventData( ...
                'EventType', 'DataChanged', ...
                'Property', 'Data3', ...
                'Model', self );
            self.notify('DataChanged', evt);
        end

        %% Event callback
        function onDataChanged(self, ~, evt)
            switch evt.Property
                case 'Data1'
                    self.Data2 = self.Data1 + 5;
                case 'Data2'
                    self.Data3 = self.Data2 + 10;
            end
        end
    end
end

If one debugs this, one sees that onDataChanged is never called with the uiw.event.eventData with evt.Property = 'Data2'.

Das anyone know why and how to trigger the event properly?

Upvotes: 1

Views: 74

Answers (1)

Rotem
Rotem

Reputation: 32084

I think I solved the puzzle.

Your code executes the listener callback recursively.
By default recursive listener is disabled.

Refer to Event and Listener Concepts:

Recursive — Allow listener to trigger the same event that caused execution of the callback. Recursive is false by default. If the callback triggers the event for which it is defined as the callback, the listener cannot execute recursively. Therefore, set Recursive to false if the callback must trigger its own event. Setting the Recursive property to true can create a situation where infinite recursion reaches the recursion limit and triggers an error.

All you need to do is setting Recursive property to true:

After self.DataChangedListener = event.listener(self, 'DataChanged', @self.onDataChanged);

Add: self.DataChangedListener.Recursive = true;

Upvotes: 1

Related Questions