gusucode.com > datatools工具箱 matlab源码程序 > datatools/inspector/matlab/+internal/+matlab/+inspector/MLInspectorDataModel.m

    classdef MLInspectorDataModel < ...
        internal.matlab.variableeditor.MLHandleObjectDataModel
    
    % This class is unsupported and might change or be removed without
    % notice in a future version.
    
    % DataModel for the Property Inspector.  Overrides the
    % MLObjectDataModel so the setData can be short-circuited for handle
    % objects (and objects which implement the InspectorProxyMixin
    % interface).
    
    % Copyright 2015 The MathWorks, Inc.
    
    properties(Hidden = true)
        ChangedProperties;
    end
    
    methods
        % Constructor - creates a new MLInspectorDataModel for a variable
        % with the specified name and workspace
        function this = MLInspectorDataModel(name, workspace)
            this@internal.matlab.variableeditor.MLHandleObjectDataModel(...
                name, workspace);
        end
        
        % Called to set the data on the object.  varargin is the Property
        % Name and Value.
        function varargout = setData(this, varargin)
            index = find(strcmp(properties(this.Data), varargin{1}));
            if isa(this.Data, 'handle')
                setPropertyValue(this.Data, ...
                    varargin{1}, ...  % Property Name
                    varargin{2});     % New value
                varargout = {};
                
                % Trigger DataChange event
                eventdata = ...
                    internal.matlab.variableeditor.DataChangeEventData;
                eventdata.Range = [index, 1];
                eventdata.Values = varargin{2};
                this.notify('DataChange', eventdata);
            else
                % set name and call super method
                varargout{1} = ...
                    setData@internal.matlab.variableeditor.MLObjectDataModel(...
                    this, varargin{2}, index, [], []);
            end
        end
        
        function data = updateData(this, varargin)
            s = warning('off', 'all');
            data = varargin{1};
            
            if ~isa(data, 'handle')
                d = this.PreviousData;
                if ~isempty(d)
                    % Compare as a struct, just as a way to compare the
                    % the old and new data
                    dataStruct = ...
                        internal.matlab.inspector.Utils.createStructForObject(...
                        data);
                    
                    if ~isequaln(d, dataStruct)
                        this.DataChanged = true;
                        
                        props1 = fieldnames(d);
                        props2 = fieldnames(dataStruct);
                        if isequal(sort(props1), sort(props2))
                            changedIdx = cellfun(@(x) ~isequaln(...
                                d.(x), dataStruct.(x)), props1);
                            changedProps = props1(changedIdx);
                            this.ChangedProperties = changedProps;
                            this.DataChanged = true;
                            for i = 1:length(changedProps)
                                propName = changedProps{i};
                                dispValue = ...
                                    internal.matlab.variableeditor.peer.PeerStructureViewModel.getDisplayEditValue(...
                                    data.(propName));
                                
                                this.Data.setPropertyValue(propName, ...
                                    data.(propName), ...
                                    dispValue, this.Name);
                            end
                        else
                            this.ChangedProperties = setdiff(...
                                sort(props2), sort(props1));
                        end
                    end
                    this.PreviousData = dataStruct;
                else
                    this.PreviousData = ...
                        internal.matlab.inspector.Utils.createStructForObject(...
                        data);
                end
            end
            warning(s);
        end
        
        function checkForUnobservableUpdates(this)
            % Checks to see if any properties have changed between the
            % original object and the proxy object (this can happen with
            % non-observable properties).  If any changes are detected,
            % then the proxy object's properties are re-initialized with
            % the current values from the original object
            if isa(this.Data, 'internal.matlab.inspector.InspectorProxyMixin')
                
                % See if there were any changes, and what properties
                % changed
                [changed, changedProps, changedProxyProps] = ...
                    OrigObjectChange(this.Data);
                if changed
                    % Reinitialize the properties from the original object
                    reinitializeFromOrigObject(this.Data, changedProps, ...
                        changedProxyProps);
                    this.DataChanged = true;
                    this.ChangedProperties = unique(vertcat(...
                        changedProps, changedProxyProps));
                end
            end
        end
        
        function handleUpdateTimer(this)
            if ~isobject(this.Data) || ~isvalid(this.Data)
                % Stop the timer if the object has been deleted
                this.stopTimer;
            else
                % Check to see if any SetObservable=false properties have
                % changed
                this.checkForUnobservableUpdates;
                
                if this.DataChanged
                    % If the data has changed, fire an event
                    if ~isempty(this.ChangedProperties)
                        props = properties(this.getData);
                        for idx=1:length(this.ChangedProperties)
                            % Typically only one property changes at a time,
                            % but it can be multiple if there are dependent
                            % properties.  But this is rare, so firing an event
                            % for each property should be ok.
                            propName = this.ChangedProperties{idx};
                            if ismember(propName, props)
                                value = this.getData.(propName);
                            
                                % Fire property changed event
                                this.firePropertyChangedEvent(...
                                    this.ChangedProperties{idx}, value);
                            elseif ~isprop(this.getData, propName)
                                % Fire property removed event if it isn't a
                                % property of data (it may be a hidden
                                % property, which we shouldn't report as
                                % being removed)
                                disp(['Property Removed: ' propName]);
                                this.firePropertyRemovedEvent(propName, '');
                            end
                        end
                    end
                    % Reset the DataChanged and Changed Properties flags
                    this.DataChanged = false;
                    this.ChangedProperties = {};
                end
            end
        end
    end
    
    methods(Access = protected)
        function updateChangeListeners(this, obj)
            % Override the super method, because we know the inspector is
            % always dealing with a proxy object
            this.removeChangeListeners();
            
            % Add listeners for dynamic properties being added or
            % removed
            this.PropAddedListener = event.listener(obj, ...
                'PropertyAdded', @this.propAddedCallback);
            this.PropRemovedListener = event.listener(obj, ...
                'PropertyRemoved', @this.propRemovedCallback);
            
            % Add listeners for all dynamically added properties of the
            % mixin
            p = properties(obj);
            for i=1:length(p)
                this.PropChangedListener{i} = event.proplistener(obj, ...
                    findprop(obj, p{i}), 'PostSet', ...
                    @this.propChangedCallback);
            end
        end
    end
end