gusucode.com > appdesigner工具箱matlab源码程序 > appdesigner/+appdesigner/+internal/+codegeneration/+model/CodeData.m

    classdef CodeData < handle...
        & appdesigner.internal.model.AbstractAppDesignerModel
    %CodeData code model data from the client
    
    % Copyright 2015-2016 The MathWorks, Inc.
    properties
        % the class name of the App
        GeneratedClassName;
        
        % an array of callbacks of type
        % 'appdesigner.internal.codegeneration.model.AppCallback'
        Callbacks;
        
        % the startup function object that can be modified of type
        % 'appdesigner.internal.codegeneration.model.AppCallback'
        ConfigurableStartupFcn;
        
        % the editable section created by the user...  properties and
        % functions.  It is an object of type 'appdesigner.internal.codegeneration.model.CodeSection'
        EditableSection;
        
        % an property to access the generated code
        GeneratedCode
    end
    
    properties
        % properties maintained for forward and backward compatibility
        
        % the startup function object of type
        % 'appdesigner.internal.codegeneration.model.AppCallback'
        % introduced in R2016a to hold the startup function for Apps
        % this is replaced by ConfigurableStartupFcn in R2016b
        StartupFcn;
    end
    
    properties(Transient, Hidden)
        % If an app has been saved to a file we will keep a copy of the
        % file's code for comparison in App Designer compatibility between
        % versions
        AppFileCode;
    end
    
    methods
        %------------------------------------------------------------------
        
        function obj = CodeData(appModel, proxyView)
            % constructor
            
            import appdesigner.internal.codegeneration.model.AppCallback;
            import appdesigner.internal.codegeneration.model.CodeSection;
            
            % create an empty array for the callback and code data
            obj.Callbacks = AppCallback.empty;
            
            % create the startup function callback
            obj.ConfigurableStartupFcn = AppCallback;
            
            obj.EditableSection = CodeSection('EditableSection', '');
            
            if (nargin > 0)
                assignToAppModel(obj, appModel, proxyView);
            end
        end
        %------------------------------------------------------------------
        
        function assignToAppModel(obj, appModel, proxyView)
            
            import appdesigner.internal.codegeneration.getAppFileCode;
            
            % assign this object to the App Model handle
            appModel.CodeData = obj;
            
            % check if the CodeData is loaded From a file
            if(~isempty(appModel.FullFileName))
                obj.AppFileCode = getAppFileCode(appModel.FullFileName);
            end
            
            % instantiate a controller for this dataC
            obj.createController(proxyView);
        end
        %------------------------------------------------------------------
        
        function set.GeneratedClassName(obj, name)
            % set the generated class name for the App
            obj.GeneratedClassName = name;
        end
        %------------------------------------------------------------------
        
        function sendGoToLineColumnEventToClient(obj, line, column, scrollToView)
            % send gotoLineColumn peerEvent to CodeModel on client side
            % TODO: this function needs to be refactored/moved. It is
            % necessary for code realted functionality but is not related
            % to code data
            obj.Controller.ProxyView.sendEventToClient('goToLineColumn', ...
                {'Line', line, 'Column', column, 'ScrollToView', scrollToView});
        end
        %------------------------------------------------------------------
        
        function data = getCodeDataForLoad(obj)
            % returns a struct to be sent to the client after
            % deserialization
            
            import appdesigner.internal.codegeneration.model.CodeData;
            
            data = struct('GeneratedClassName', obj.GeneratedClassName, ...
                'EditableSection', CodeData.convertObjectToStruct(obj.EditableSection) , ...
                'Callbacks',  CodeData.convertObjectToStruct(obj.Callbacks), ...
                'StartupFcn', CodeData.convertObjectToStruct(obj.ConfigurableStartupFcn));
            
        end
        %------------------------------------------------------------------
    end
    
    methods(Access=private, Static)
        %------------------------------------------------------------------
        
        function codeStruct = convertObjectToStruct(objectArray)
            import appdesigner.internal.codegeneration.model.CodeData;
            % helper method to convert MCOS objects contained in this class
            % into structs
            codeStruct = struct();
            codeDataProps = properties(objectArray);
            versionProperties = properties(appdesigner.internal.serialization.app.AppVersion);
            for i = 1:length(objectArray)
                for j = 1:length(codeDataProps)
                    % remove properties inherted from AppVersion  for code
                    % Data objects
                    if (~ismember(codeDataProps{j}, versionProperties))
                        prop = objectArray(i).(codeDataProps{j});
                        if(isobject(prop))
                            codeStruct(i).(codeDataProps{j}) =  CodeData.convertObjectToStruct(prop);
                        else
                            codeStruct(i).(codeDataProps{j}) = prop;
                        end
                    end
                end
            end
        end
        %------------------------------------------------------------------
    end
    
    methods(Access = public)
        %------------------------------------------------------------------
        
        function controller = createController(obj,  proxyView)
            % Creates the controller for this Model
            controller = appdesigner.internal.codegeneration.controller.CodeDataController(obj, proxyView);
        end
        %------------------------------------------------------------------
    end
    
    methods(Static, Hidden)
        
        %------------------------------------------------------------------
        
        function obj = loadobj(loadedObj)
            % handles loading the CodeData Object from a MAT file. This is
            % used for maintaining backward compatibilty between releases
            % of App Designer. loadobj is a point when unserializing App
            % Designer data to modify the loaded object to make it
            % compatibile to the current release of App Designer
            
            import appdesigner.internal.codegeneration.model.*;
            
            % update the returned obj to have the same data as loadedObj
            if isstruct(loadedObj)
                % MCOS will pass a struct into loadobj() when load() can't
                % create the object directly, e.g. class definition
                % changes.
                % In this case, 16a AppCallback inherits from AppVersion,
                % but removed in 16b (g1398205). So when loading an 16a app
                % into 16b, the loadedObj would be a struct
                obj = appdesigner.internal.codegeneration.model.CodeData();
                
                fieldNames = fieldnames(loadedObj);
                for i = 1:length(fieldNames)
                    propName = fieldNames{i};                    
                    if isprop(obj, propName)
                        obj.(propName) = loadedObj.(propName);                        
                    end
                end
            else
                % Otherwise class definition is compatible with the 
                % serialized object, and MCOS load() can instantiate the 
                % object, and loadedObj would be a regular object
                obj = loadedObj;
            end
            
            % if the loaded object is from a version earlier than the
            % current:
            % 1) copy the startupFcn data to the configurable
            % startupFcn
            % 2) convert callback.ComponentData.ComponentType from
            % 'matlab.ui.control.AppWindow' to 'matlab.ui.Figure'
            obj = CodeData.handleReleaseComaptibilty(loadedObj, obj);
        end
        %------------------------------------------------------------------
        
        function obj = handleReleaseComaptibilty(loadedObj, obj)
            % handles compatibility for loading codeData
            
            % if CodeData is loaded before the Configurable Startup
            % function exists and there is code on the Startup Function
            % transfer its data to the ConfigurableStartupFcn. Otherwise,
            % its assumed that the user deleted the Startup function and it
            % is empty
            if (isstruct(loadedObj) || isempty(loadedObj.ConfigurableStartupFcn)) && ...
                ~isempty(loadedObj.StartupFcn.Code)
                % copy the serialized StartupFcn data to ConfigurableStatipFcn
                obj.ConfigurableStartupFcn = loadedObj.StartupFcn;
            end
            
            % From 16a, the UIFigure's callback data will store
            % ComponentType as 'matlab.ui.control.AppWindow', and in order
            % to load into 16b or later, need to change to
            % 'matlab.ui.Figure'
            %
            % Shared callback has multiple ComponentData, and strcmp
            % requires one string
            function convertAppWindowTypeToFigure(componentData)
                if strcmp(componentData.ComponentType, 'matlab.ui.control.AppWindow')
                    componentData.ComponentType = 'matlab.ui.Figure';
                end
            end
            arrayfun(@convertAppWindowTypeToFigure, [obj.Callbacks.ComponentData]);
        end
        %------------------------------------------------------------------
    end
    
    methods(Hidden)
        %------------------------------------------------------------------
        function savedObj = saveobj(obj)
            % handles saving the CodeData object to MAT file. This function
            % is used for maintaining forward compatibility in that the
            % saved app can be modified before serialzation to a MAT file.
            
            % update the returned obj to have the same data as obj
            savedObj = obj;
            savedObj = obj.handleSaveStartupFcnForCompatibility(savedObj);
            
        end
        %------------------------------------------------------------------
        
        function savedObj = handleSaveStartupFcnForCompatibility(obj, savedObj)
            % save the StartupFcn for forward compatibility reasons,
            % earlier releases (16a) used this property for the startup
            % function.
            % this data is hard-coded to be reflective of the default
            % startup callback in prior releases.
            
            import appdesigner.internal.codegeneration.model.*;
            
            startupFcn = AppCallback();
            startupFcn.Name = 'startupFcn';
            startupFcn.Comment = getString(message('MATLAB:appdesigner:codegeneration:RunStartupFcnComment'));
            startupFcn.Args = {'app'};
            startupFcn.ReturnArgs = [];
            startupFcn.Type = 'AppStartupFunction';
            startupFcn.ComponentData  = CallbackComponentData.empty;
            startupFcn.CallbackId  = [];
            
            if (~isempty(obj.ConfigurableStartupFcn))
                startupFcn.Code = obj.ConfigurableStartupFcn.Code;
            else
                startupFcn.Code = [];
            end
            
            savedObj.StartupFcn = startupFcn;
        end
        %------------------------------------------------------------------
    end
    
    
end