gusucode.com > datatools工具箱 matlab源码程序 > datatools/inspector/matlab/+internal/+matlab/+inspector/+peer/InspectorFactory.m
classdef InspectorFactory < handle % This class is unsupported and might change or be removed without % notice in a future version. % This class is the peer Inspector Factory for the Property Inspector % Copyright 2015-2016 The MathWorks, Inc. properties (Constant) % PeerModelChannel PeerModelChannel = '/InspectorPropertyManager'; % Force New Instance % Used to force creation of a new instance for testing purposes ForceNewInstance = 'force_new_instance'; % Default Cache Path CachePath = fullfile(matlabroot,'toolbox','matlab','datatools','inspector','registration'); % Default Cache File Name CacheFileName = 'inspectorProxyViewMapCache.mat'; % Default Proxy View Mapping File Cache DefaultProxyViewMapCacheFile = fullfile(... internal.matlab.inspector.peer.InspectorFactory.CachePath,... internal.matlab.inspector.peer.InspectorFactory.CacheFileName); end properties (SetAccess = protected) % Peer Manager and Channel for the Property Inspector PeerManager; Channel = ... internal.matlab.inspector.peer.InspectorFactory.PeerModelChannel; % Peer Event Listener PeerEventListener; % Property Event Listener PropertySetListener; % Temp Inspector TempInspector; % Proxy View Mapping File Cache ProxyViewMapCacheFile = internal.matlab.inspector.peer.InspectorFactory.DefaultProxyViewMapCacheFile; end % ProxyViewMap properties (SetObservable=true, SetAccess='protected', GetAccess='public', Dependent=false, Hidden=true) % ProxyViewMap Property ProxyViewMap@containers.Map = containers.Map; % ProxyViewMapJSON Property ProxyViewMapJSON@containers.Map = containers.Map; end %properties events InspectorFocusGained; % Sent from the factory when a manager gains focus InspectorFocusLost; % Sent from the factory when manager loses focus end methods (Access = protected) function this = InspectorFactory() this.loadCacheFile(this.ProxyViewMapCacheFile); % Create a temporary inspector n = strsplit(tempname, '\\'); n = n{end}; this.TempInspector = ... internal.matlab.inspector.peer.PeerInspectorManager(n, ['/' n]); % Creates a new InspectorFactory instance Root = ... [internal.matlab.inspector.peer.InspectorFactory.PeerModelChannel ... '_Root']; % Create new Peer Manager this.PeerManager = ... internal.matlab.variableeditor.peer.PeerManager(... internal.matlab.inspector.peer.InspectorFactory.PeerModelChannel, ... Root, true); % Add peer event listener this.PeerEventListener = ... event.listener(this.PeerManager.PeerModelServer.getRoot, ... 'PeerEvent', @this.handlePeerEvent); % Add Property Set Listener this.PropertySetListener = event.listener(... this.PeerManager.PeerModelServer.getRoot, 'PropertySet', ... @this.handlePropertySet); % Set initialized property on the PeerManager this.PeerManager.setProperty('Initialized', true); % Send the maps to the client this.sendProxyViewMapToClient(); % Send event for the factory ready internal.matlab.variableeditor.peer.PeerUtils.sendPeerEvent(... this.PeerManager.getRoot(), 'FactoryInitialized'); end function loadCacheFile(this, filePath) % Creates the proxyview map this.ProxyViewMap = containers.Map; this.ProxyViewMapJSON = containers.Map; if exist(this.ProxyViewMapCacheFile, 'file') s = load(filePath); this.ProxyViewMap = s.ProxyViewMap; this.ProxyViewMapJSON = s.ProxyViewMapJSON; end end function saveProxyViewMapCacheFile(this) ProxyViewMap = this.ProxyViewMap; %#ok<NASGU,PROP> ProxyViewMapJSON = this.ProxyViewMapJSON; %#ok<NASGU,PROP> save(this.ProxyViewMapCacheFile,... 'ProxyViewMap','ProxyViewMapJSON'); % Send the maps to the client this.sendProxyViewMapToClient(); end function sendProxyViewMapToClient(this) % Generate the JSON Array of all proxy view mappings appKeys = keys(this.ProxyViewMapJSON); jsonStr = '['; for i=1:length(appKeys) app = appKeys{i}; map = this.ProxyViewMapJSON(app); classKeys = keys(map); for j=1:length(classKeys) class = classKeys{j}; classJSON = map(class); if length(jsonStr)>1 jsonStr = [jsonStr ',']; %#ok<AGROW> end jsonStr = [jsonStr classJSON]; %#ok<AGROW> end end jsonStr = [jsonStr ']']; this.PeerManager.setProperty('ProxyViewMap', ... jsonStr); end function updateProxyClassMapping(this, className, application, proxyClass, proxyJSON) if ~isKey(this.ProxyViewMap, application) this.ProxyViewMap(application) = containers.Map; this.ProxyViewMapJSON(application) = containers.Map; end if nargin<4 || isempty(proxyClass) proxyClass = []; end if nargin<5 || isempty(proxyJSON) proxyJSON = ''; end % Get the class name maps map = this.ProxyViewMap(application); jsonMap = this.ProxyViewMapJSON(application); % Update classname maps map(className) = proxyClass; jsonMap(className) = proxyJSON; % Store changes back this.ProxyViewMap(application) = map; this.ProxyViewMapJSON(application) = jsonMap; this.saveProxyViewMapCacheFile(); end end methods % Handles all peer events from the client function handlePeerEvent(this, ~, ed) if isfield(ed.EventData,'source') && ... strcmp('server',ed.EventData.source) % Ignore events generated by the server return; end if isfield(ed.EventData,'type') try switch ed.EventData.type case 'CreateInspector' % Fired to start a server peer manager for an % inspector this.logDebug('InspectorFactory', ... 'handlePeerEvent', 'CreateInspector'); this.createInspector(ed.EventData.application, ... ed.EventData.channel); case 'DeleteInspector' % Fired to delete a server peer manager % inspector this.logDebug('InspectorFactory', ... 'handlePeerEvent', 'DeleteInspector'); % Get the manager instance and delete it if this.getInspectorInstances.isKey(... ed.EventData.channel) % Get the Property Inspector which is % referenced by the key manager = this.createInspector(... ed.EventData.application, ... ed.EventData.channel); % Delete the Property Inspector delete(manager); end case 'RegisterInspectorView' % Fired to start a server peer manager for an % inspector this.logDebug('InspectorFactory', ... 'handlePeerEvent', 'RegisterInspectorView'); if isfield(ed.EventData,'defaultObj') obj = ed.EventData.defaultObj; else obj = ''; end this.registerInspectorView(... ed.EventData.className,... ed.EventData.application,... ed.EventData.proxyViewClass,... obj); end catch e % Send the error message back to the client this.sendErrorMessage(e.message); end end end function status = handlePropertySet(~, ~, ed) % Handles properties being set. ed is the Event Data, and it % is expected that ed.EventData.key contains the property which % is being set. Returns a status: empty string for success, an % error message otherwise. status = ''; if ~isa(ed.EventData.newValue, 'java.util.HashMap') return; end if ed.EventData.newValue.containsKey('Source') && ... strcmp('server',ed.EventData.newValue.get('Source')) % Ignore events generated by the server return; end end function logDebug(this, class, method, message, varargin) % Logs debug information using PeerUtils rootNode = this.PeerManager.getRoot(); internal.matlab.variableeditor.peer.PeerUtils.logDebug(... rootNode, class, method, message, varargin{:}); end function sendErrorMessage(this, message) % Sends an error message to the client this.PeerManager.getRoot.dispatchEvent(struct(... 'type', 'error', ... 'message', message, ... 'source','server')); end end methods (Static, Access = protected) function runRegistrator(className) try evalStr = sprintf('isa(%s, ''internal.matlab.inspector.peer.InspectorRegistrator'')', className); fprintf('Registering Inspector Components: %s\n', className); instance = eval(className); instance.registerInspectorComponents; catch e fprintf('!!! Failed To Register Components for: %s\n', className); fprintf('\t%s\n', e.message); end end function runRegistratorsInPath(startPath) if (nargin < 1) || isempty(startPath) startPath = 'internal'; end mClasses = internal.findSubClasses(startPath,... 'internal.matlab.inspector.peer.InspectorRegistrator', true); for i=1:length(mClasses) className = mClasses{i}.Name; internal.matlab.inspector.peer.InspectorFactory.runRegistrator(className); end end end methods(Static) % getInstance - returns an instance of the Inspector Factory function obj = getInstance(varargin) mlock; % Keep persistent variables until MATLAB exits persistent managerInstance; if isempty(managerInstance) || ~isvalid(managerInstance) || ... (nargin>0 && ... strcmpi(varargin{1}, ... internal.matlab.workspace.peer.PeerManager.ForceNewInstance)) % Create a new Inspector Factory managerInstance = ... internal.matlab.inspector.peer.InspectorFactory; end obj = managerInstance; end function obj = getInspectorInstances(newInspectorInstances) % Returns the list of inspector instances that have been % created. mlock; % Keep persistent variables until MATLAB exits persistent InspectorInstances; % Factory Instance factoryInstance = ... internal.matlab.inspector.peer.InspectorFactory.getInstance; if nargin > 0 % Set the new inspector instances InspectorInstances = newInspectorInstances; factoryInstance.logDebug('InspectorFactory', ... 'getInspectorInstances', 'set'); keys = InspectorInstances.keys(); managerJSON = ['[' sprintf('"%s",',keys{:})]; managerJSON(end) = ']'; factoryInstance.PeerManager.setProperty('Managers', ... managerJSON); elseif isempty(InspectorInstances) % Create the inspectorInstances map for the first time factoryInstance.logDebug('InspectorFactory', ... 'getInspectorInstances', 'initial creation'); InspectorInstances = containers.Map(); else factoryInstance.logDebug('InspectorFactory', ... 'getInspectorInstances', 'get'); end % Return the inspector instances map obj = InspectorInstances; end function varargout = createInspector(Application, Channel) % Creates a Property Inspector mlock; % Keep persistent variables until MATLAB exits persistent inspectorCounter; persistent deleteListeners; if isempty(inspectorCounter) inspectorCounter = 0; end if nargin<1 || isempty(Application) % Setup a default application if it wasn't provided Application = 'default'; end % Update the counter inspectorCounter = inspectorCounter + 1; if nargin<2 || isempty(Channel) % Setup a default channel if it wasn't provided Channel = ['/Inspector_' num2str(inspectorCounter)]; end % Get the factory instance factoryInstance = ... internal.matlab.inspector.peer.InspectorFactory.getInstance; factoryInstance.logDebug('InspectorFactory', 'createManager', ... '', 'Application', Application, 'Channel', Channel); % Get the list of inspector instances InspectorInstances = ... internal.matlab.inspector.peer.InspectorFactory.getInspectorInstances; if isempty(deleteListeners) deleteListeners = containers.Map(); end if ~isKey(InspectorInstances, Channel) % Create a new Peer Inspector Manager instance managerInstance = ... internal.matlab.inspector.peer.PeerInspectorManager(... Application, Channel); InspectorInstances(Channel) = managerInstance; % Add a listener for when it is destroyed deleteListeners(Channel) = event.listener(managerInstance,... 'ObjectBeingDestroyed',... @(es,ed) (internal.matlab.inspector.peer.InspectorFactory.getInspectorInstances(... InspectorInstances.remove(Channel)))); internal.matlab.inspector.peer.InspectorFactory.getInspectorInstances(InspectorInstances); end % Return the new manager instances obj = InspectorInstances(Channel); % Send event for the manager creation internal.matlab.variableeditor.peer.PeerUtils.sendPeerEvent(... factoryInstance.PeerManager.getRoot(), 'InspectorCreated', ... 'Application', obj.Application, 'Channel', Channel); if nargout == 1 % Return the inspector instance if an argument is expected varargout = {obj}; end end function destroyInspector(objOrKey) % Deletes the specified inspector. objOrKey can be the % Inspector object, or it can be a key (the channel ID) inspectorInstances = ... internal.matlab.inspector.peer.InspectorFactory.getInspectorInstances; if ischar(objOrKey) % This is a key, look for it in the list of instances if isKey(inspectorInstances, objOrKey) % delete this instance delete(inspectorInstances(objOrKey)); end else % This is an inspector instance, find it in the map and % delete it allKeys = keys(inspectorInstances); for i = 1:length(allKeys) key = allKeys{i}; if isequal(inspectorInstances(key), objOrKey) delete(objOrKey); break; end end end end function registerEditor(className, clientEditorPath) % Register an editor for a given class name wr = internal.matlab.variableeditor.peer.WidgetRegistry.getInstance; wr.registerEditor(... 'internal.matlab.inspector.peer.PeerInspectorViewModel',... className, clientEditorPath); end function registerInPlaceEditor(className, clientEditorPath) % Register an in-place editor for a given class name wr = internal.matlab.variableeditor.peer.WidgetRegistry.getInstance; wr.registerInPlaceEditor(... 'internal.matlab.inspector.peer.PeerInspectorViewModel',... className, clientEditorPath); end function registerRenderer(className, clientRendererPath) % Register a renderer for a given class name wr = internal.matlab.variableeditor.peer.WidgetRegistry.getInstance; wr.registerCellRenderer(... 'internal.matlab.inspector.peer.PeerInspectorViewModel',... className, clientRendererPath); end function registerEditorConverter(variableClass, converter) % Register a renderer for a given class name wr = internal.matlab.variableeditor.peer.WidgetRegistry.getInstance; wr.registerEditorConverter('internal.matlab.inspector.peer.PeerInspectorViewModel',... variableClass,... converter); end function registerInspectorView(className, application, propertySheet, defaultObj) % Factory Instance factoryInstance = ... internal.matlab.inspector.peer.InspectorFactory.getInstance; if nargin<2 || isempty(application) application = 'default'; end if nargin<1 || isempty(className) className = 'default'; end if ~isKey(factoryInstance.ProxyViewMap, application) factoryInstance.ProxyViewMap(application) = containers.Map; factoryInstance.ProxyViewMapJSON(application) = containers.Map; end % Get the class name maps map = factoryInstance.ProxyViewMap(application); if isKey(map, className) return; end if nargin<3 || isempty(propertySheet) % Get the class name maps map = factoryInstance.ProxyViewMap(application); jsonMap = factoryInstance.ProxyViewMapJSON(application); % Update classname maps map(className) = []; jsonMap(className) = ''; % Store changes back factoryInstance.ProxyViewMap(application) = map; factoryInstance.ProxyViewMapJSON(application) = jsonMap; return; end if ~isa(propertySheet, 'internal.matlab.inspector.InspectorProxyMixin') &&... ~ischar(propertySheet) %TODO: put this in the message catalog error('Property Sheet must extend internal.matlab.inspector.InspectorProxyMixin'); end % If a default object is not passed in attempt to create an % instance of one of the passed in classes if (nargin<4 || isempty(defaultObj)) &&... ~isa(propertySheet, 'internal.matlab.inspector.InspectorProxyMixin') defaultObj = []; %#ok<NASGU> % try to create an instance of the class if ~strcmp(className, 'default') defaultObj = eval([className '()']); %#ok<NASGU> if ismember('matlab.graphics.Graphics', superclasses(className)) drawnow('nocallbacks'); end end end % Try to create an instance of the proxy object try jsonData = '{}'; proxyObject = propertySheet; if ~isa(propertySheet, 'internal.matlab.inspector.InspectorProxyMixin') s = struct('application', application, 'className', className); proxyObject = eval([propertySheet '(defaultObj)']); if ~isa(proxyObject, 'internal.matlab.inspector.InspectorProxyMixin') %TODO: put this in the message catalog error('Property Sheet must extend internal.matlab.inspector.InspectorProxyMixin'); end end % Create a temporary inspector factoryInstance.TempInspector.inspect(proxyObject); factoryInstance.TempInspector.Documents(1).ViewModel.DataModel.stopTimer; rows = factoryInstance.TempInspector.Documents(1).ViewModel.getSize(); rows = rows(1); rd = factoryInstance.TempInspector.Documents(1).ViewModel.getRenderedData(1,rows,1,1); s.defaults = strcat(rd{:}); jsonData = internal.matlab.variableeditor.peer.PeerUtils.toJSON(true, s); factoryInstance.TempInspector.closeAllVariables(); catch e factoryInstance.logDebug('InspectorFactory', ... 'handlePeerEvent', e.message); error(e.message); end % Update the client mapping factoryInstance.updateProxyClassMapping(className, application, class(proxyObject), jsonData); end function proxyClass = getInspectorView(className, application) proxyClass = []; % Factory Instance factoryInstance = ... internal.matlab.inspector.peer.InspectorFactory.getInstance; if nargin<2 || isempty(application) application = 'default'; end if nargin<1 || isempty(className) className = 'default'; end if ~isKey(factoryInstance.ProxyViewMap, application) return; end % Get the class name maps map = factoryInstance.ProxyViewMap(application); if ~isKey(map, className) return; end proxyClass = map(className); end function clearInspectorViewCache() % Factory Instance factoryInstance = ... internal.matlab.inspector.peer.InspectorFactory.getInstance; factoryInstance.ProxyViewMap = containers.Map; factoryInstance.ProxyViewMapJSON = containers.Map; factoryInstance.saveProxyViewMapCacheFile(); end function buildRegistration(outputFile, varargin) if nargin<1 || isempty(outputFile) outputFile = internal.matlab.inspector.peer.InspectorFactory.CachePath; end % Factory Instance factoryInstance = ... internal.matlab.inspector.peer.InspectorFactory.getInstance; currentProxyViewMap = factoryInstance.ProxyViewMap; currentProxyViewMapJSON = factoryInstance.ProxyViewMapJSON; factoryInstance.ProxyViewMap = containers.Map; factoryInstance.ProxyViewMapJSON = containers.Map; % Clear the current data if exist(outputFile, 'file') delete(outputFile); end factoryInstance.ProxyViewMapCacheFile = fullfile(outputFile); if nargin>1 internal.matlab.inspector.peer.InspectorFactory.runRegistratorsInPath(varargin{1}); else internal.matlab.inspector.peer.InspectorFactory.runRegistratorsInPath(); end factoryInstance.ProxyViewMapCacheFile = internal.matlab.inspector.peer.InspectorFactory.DefaultProxyViewMapCacheFile; factoryInstance.ProxyViewMap = currentProxyViewMap; factoryInstance.ProxyViewMapJSON = currentProxyViewMapJSON; end function deregisterApplicationInspectorViews(application) % Factory Instance factoryInstance = ... internal.matlab.inspector.peer.InspectorFactory.getInstance; if nargin<1 || isempty(application) application = 'default'; end % Store changes back factoryInstance.ProxyViewMap(application) = containers.Map; factoryInstance.ProxyViewMapJSON(application) = containers.Map; factoryInstance.saveProxyViewMapCacheFile(); end function deregisterInspectorView(className, application) % Factory Instance factoryInstance = ... internal.matlab.inspector.peer.InspectorFactory.getInstance; if nargin<2 || isempty(application) application = 'default'; end if nargin<1 || isempty(className) className = 'default'; end % Update the client mapping factoryInstance.updateProxyClassMapping(className, application, [], []); end function setProxyCacheFile(filePath) % Factory Instance factoryInstance = ... internal.matlab.inspector.peer.InspectorFactory.getInstance; factoryInstance.ProxyViewMapCacheFile = filePath; factoryInstance.loadCacheFile(filePath); end function startup() % Makes sure the peer manager for the variable editor exists internal.matlab.inspector.peer.InspectorFactory.getInstance(); end end end