www.gusucode.com > mbcguitools 工具箱 matlab 源码程序 > mbcguitools/+mbcgui/+multiview/ViewList.m

    classdef ViewList < matlab.mixin.SetGet & matlab.mixin.Copyable
    %mbcgui.multiview.ViewList class
    %    mbcgui.multiview.ViewList properties:
    %       ConstructorFcns - Property is of type 'MATLAB array' (read only)
    %       Labels - Property is of type 'MATLAB array' (read only)
    %       IconFiles - Property is of type 'MATLAB array' (read only)
    %       Descriptions - Property is of type 'MATLAB array' (read only)
    %       MaxRecommended - Property is of type 'MATLAB array' (read only)
    %
    %    mbcgui.multiview.ViewList methods:
    %       addFromExtensions - Add views from extensions
    %       addViews - Add new view information to the ViewList
    %       createView - Create a view
    %       findViewLabel - Find a view given a label
    %       getIconForView - Get a bitmap icon for a view
    %       isViewAvailable - Check whether a view is available
    %       numViews - Return the number of views that are listed
    
    %  Copyright 2005-2015 The MathWorks, Inc. and Ford Global Technologies, Inc.
    
    properties (Access=protected, AbortSet)
        %VIEWID Property is of type 'MATLAB array'
        ViewID = [];
        %NEXTVIEWID Property is of type 'int'
        NextViewID=0;
        %DESTRUCTIONLISTENERS Property is of type 'MATLAB array'
        DestructionListeners = {  };
    end
    
    properties (SetAccess=protected, AbortSet)
        %CONSTRUCTORFCNS Property is of type 'MATLAB array' (read only)
        ConstructorFcns = cell(1,0);
        %LABELS Property is of type 'MATLAB array' (read only)
        Labels = cell(1,0);
        %ICONFILES Property is of type 'MATLAB array' (read only)
        IconFiles = cell(1,0);
        %DESCRIPTIONS Property is of type 'MATLAB array' (read only)
        Descriptions = cell(1,0);
        %MAXRECOMMENDED Property is of type 'MATLAB array' (read only)
        MaxRecommended = zeros(1,0);
        %NUMCREATED Property is of type 'MATLAB array'
        NumCreated = [];
    end
    
    methods  % constructor block
        function obj = ViewList(varargin)
        %VIEWLIST Create a new ViewList object
        %
        %  OBJ = VIEWLIST constructs a new ViewList object. ViewList encapsulates a
        %  set of View descriptions that comprise constructor, label, icon,
        %  description and the maximum number of instances for a view.
        %
        %  OBJ = VIEWLIST(CONSTRUCTORS, LABELS, ICONS, DESCRIPTIONS, MAXVIEW) seeds
        %  the new object with the given data.
        %
        %  DATA FORMAT
        %  ===========
        %
        %  CONSTRUCTORS  :  Cell array of construction functions, one for each
        %                   view.  A construction function must be either a string
        %                   or a function handle to a function that accepts
        %                   arguments in the standard component Property-Value
        %                   syntax, and returns a handle to a View object.
        %
        %  LABELS        :  Cell array of strings that are suitable for placing on
        %                   a menu item that creates the view.  A preferred
        %                   mnemonic character should be included in the string,
        %                   although the mnemonic may be altered if it clashes with
        %                   another view.
        %
        %  ICONS         :  Cell array of strings that contains the full path of a
        %                   (16-by-16) icon that can be used to represent the view
        %                   on a toolbar button.  This may be left empty, in which
        %                   case the view will not automatically be added to
        %                   toolbars.
        %
        %  DESCRIPTIONS  :  Cell array of strings that are suitable for using as
        %                   tooltip descriptions for the view's toolbar button.
        %                   This may be left empty.
        %
        %  MAXVIEW       :  Vector of numbers that are >=1, one for each view. This
        %                   number defines the maximum number of views that it is
        %                   useful for a user to have open at once.  Specify inf if
        %                   you do not want to think about this.
        
        if nargin && isa(varargin{1}, 'mbcgui.multiview.ViewList')
            obj = varargin{1};
            varargin(1) = [];
        else
            %     obj = mbcgui.multiview.ViewList;
        end
        
        if ~isempty(varargin)
            obj.addViews(varargin{:});
        end
        
        end  % ViewList
        
    end  % constructor block
    
    methods
        function set.ConstructorFcns(obj,value)
        obj.ConstructorFcns = i_checkcell(obj,value);
        end
        
        function set.Labels(obj,value)
        obj.Labels = i_checkcell(obj,value);
        end
        
        function set.IconFiles(obj,value)
        obj.IconFiles = i_checkcell(obj,value);
        end
        
        function set.Descriptions(obj,value)
        obj.Descriptions = i_checkcell(obj,value);
        end
        
        function set.MaxRecommended(obj,value)
        obj.MaxRecommended = i_checkvect(obj,value);
        end
        
        function set.NextViewID(obj,value)
        % DataType = 'int'
        validateattributes(value,{'numeric'},{'scalar'},'','NextViewID')
        value = round(value); %  round to obtain an integer
        obj.NextViewID = value;
        end
        
    end   % set and get functions
    
    methods  % public methods
        %----------------------------------------
        function addFromExtensions(obj, e, ExtName)
        %ADDFROMEXTENSIONS Add views from extensions
        %
        %  ADDFROMEXTENSIONS(OBJ, E, EXTNAME) adds any view definitions that are in
        %  the extensions object E, in the property EXTNAME.
        
        sData = get(e, ExtName);
        nViews = length(sData);
        for n = 1:nViews
            sView = sData(n);
            obj.ConstructorFcns = i_getcelldata(sView, 'Constructor', '', obj.ConstructorFcns);
            obj.Labels = i_getcelldata(sView, 'MenuLabel', '', obj.Labels);
            obj.IconFiles = i_getcelldata(sView, 'IconFile', '', obj.IconFiles);
            obj.Descriptions= i_getcelldata(sView, 'Description', '', obj.Descriptions);
            obj.MaxRecommended = i_getnumdata(sView, 'MaxRecommended', inf, obj.MaxRecommended);
        end
        
        obj.ViewID = [obj.ViewID, obj.NextViewID:(obj.NextViewID+nViews-1)];
        obj.NextViewID = obj.NextViewID + nViews;
        obj.NumCreated = [obj.NumCreated, zeros(1, nViews)];
        obj.DestructionListeners = [obj.DestructionListeners, cell(1, nViews)];
        end  % addFromExtensions
        
        %----------------------------------------
        function addViews(obj, varargin)
        %ADDVIEWS Add new view information to the ViewList
        %
        %  ADDVIEWS(OBJ, CONSTRUCTORS, LABELS, ICONS, DESCRIPTIONS, MAXVIEW) adds
        %  new views to the ViewList.  See VIEWLIST for more details on the inputs.
        
        nArgs = length(varargin);
        if nArgs
            L = cellfun('length', varargin);
            nViews = max(L);
            if any(L~=nViews & L~=0)
                error(message('mbc:mbcmultiview:ViewList:InvalidArguments'));
            end
            Props = {'ConstructorFcns', 'Labels', 'IconFiles', ...
                'Descriptions', 'MaxRecommended'};
            for n = 1:length(Props)
                val = get(obj, Props{n});
                if n<=nArgs && length(varargin{n})==nViews
                    set(obj, Props{n}, [val, varargin{n}]);
                else
                    if iscell(val)
                        set(obj, Props{n}, [val, repmat({''}, 1, nViews)]);
                    else
                        set(obj, Props{n}, [val, inf(1, nViews)]);
                    end
                end
            end
            
            obj.ViewID = [obj.ViewID, obj.NextViewID:(obj.NextViewID+nViews-1)];
            obj.NextViewID = obj.NextViewID + nViews;
            obj.NumCreated = [obj.NumCreated, zeros(1, nViews)];
            obj.DestructionListeners = [obj.DestructionListeners, cell(1, nViews)];
        end
        
        end  % addViews
        
        function add(vl,ViewInfo)
        %add add view frrom cell array of details
        %    add(vl,{Constructor,Label,IconFile,Description,MaxRecommended}
        
        % add new view to list
        vl.ConstructorFcns{1,end+1} = ViewInfo{1};
        vl.Labels{1,end+1} = ViewInfo{2};
        vl.IconFiles{1,end+1} = ViewInfo{3};
        vl.Descriptions{1,end+1} = ViewInfo{4};
        vl.MaxRecommended(1,end+1) = ViewInfo{5};
        
        % create supporting information 
        vl.ViewID = [vl.ViewID, vl.NextViewID];
        vl.NextViewID = vl.NextViewID + 1;
        vl.NumCreated = [vl.NumCreated, 0];
        vl.DestructionListeners = [vl.DestructionListeners, {[]}];
        
        end
        
        
        function enableView(obj,indexClass,status)
        %enableView enable specified view by setting MaxRecommended
        %    enableView(obj,indexClass,status)
        
        if status
           obj.MaxRecommended(indexClass) = 1; 
        else
           obj.MaxRecommended(indexClass) = 0; 
        end
        
        end
        
        %----------------------------------------
        function [hView, Index] = createView(obj, varargin)
        %CREATEVIEW Create a view
        %
        %  HVIEW = CREATEVIEW(INDEX, MS, PROP, VALUE, ...) constructs the specified
        %  view.  The view will be passed the list of properties ans the specified
        %  message service as part of the creation.
        %
        %  HVIEW = CREATEVIEW(MS, PROP, VALUE, ...) automatically chooses the view
        %  type that has the fewest instances open and creates one of them.  View
        %  availability is also checked using the MessageService MS.
        %
        %  [HVIEW, INDEX] = CREATEVIEW(...) also returns the index of the view that
        %  has been created.
        
        if nargin>1 && isnumeric(varargin{1})
            Index = varargin{1};
            varargin(1) = [];
        else
            Index = [];
        end
        MS = varargin{1};
        varargin(1) = [];
        
        if isempty(Index)
            % Choose a view
            NCreated = obj.NumCreated;
            MaxRec = obj.MaxRecommended;
            
            % For views that have hit their max, set NCreated to inf to inhibit
            % extra creation.  If all views have hit the max this will still allow
            % one of them to be chosen
            NCreated(NCreated>=MaxRec) = inf;
            
            % Check availability of views
            IsAvail = obj.isViewAvailable(MS);
            if any(IsAvail)
                % Only remove views if there will be some left
                NCreated = NCreated(IsAvail);
                AvailIndex = find(IsAvail);
            else
                AvailIndex = 1:length(obj.NumCreated);
            end
            
            [~, Index] = min(NCreated);
            Index = AvailIndex(Index);
        end
        
        if Index<=length(obj.ConstructorFcns) && Index>0
            hView = feval(obj.ConstructorFcns{Index}, ...
                'MessageService', MS, varargin{:});
            obj.NumCreated(Index) = obj.NumCreated(Index)+1;
            L = obj.DestructionListeners{Index};
            L = [L; ...
                event.listener(hView, 'ObjectBeingDestroyed', @(h,evt) i_viewclosed(h,evt,obj, obj.ViewID(Index)))];
            obj.DestructionListeners{Index} = L;
        else
            error(message('mbc:mbcmultiview:ViewList:IndexOutOfBounds'));
        end
        end  % createView
        
        %----------------------------------------
        function Index = findViewLabel(obj, Label)
        %FINDVIEWLABEL Find a view given a label
        %
        %  INDEX = FINDVIEWLABEL(OBJ, LABEL) returns the index of the view type
        %  that matches the label.  If no view matches the label, an empty index is
        %  returned.
        
        Index = find(strcmpi(obj.Labels, Label));
        
        end  % findViewLabel
        
        %----------------------------------------
        function Index = findViewClass(obj, Class)
        %findViewClass Find a view given a class
        %
        %  INDEX = findViewClass(OBJ, Class) returns the index of the view type
        %  that matches the ConstructorFcns.  If no view matches the class, an empty index is
        %  returned.
        
        Classes = cellfun(@(f) func2str(f),obj.ConstructorFcns,'UniformOutput',false);
        Index = find(strcmpi(Classes, Class));
        
        end  % findViewClass        
        
        
        %----------------------------------------
        function ic = getIconForView(obj, Index)
        %GETICONFORVIEW Get a bitmap icon for a view
        %
        %  IC = GETICONFORVIEW(OBJ, INDEX) returns the icon data for the specified
        %  view.
        
        if Index>0 && Index<=length(obj.IconFiles)
            if ~isempty(obj.IconFiles{Index})
                ic = imread(obj.IconFiles{Index}, 'bmp');
            else
                ic = zeros(0,0,3);
            end
        else
            error(message('mbc:mbcmultiview:ViewList:IndexOutOfBounds'));
        end
        
        end  % getIconForView
        
        %----------------------------------------
        function ret = isViewAvailable(obj, ~, Index)
        %ISVIEWAVAILABLE Check whether a view is available
        %
        %  ISVIEWAVAILABLE(OBJ, MS, INDEX) returns true if a view should be allowed
        %  to be made at the present time.  MS must be a handle to the
        %  MessageService that the view will be displaying data from.
        %
        %  ISVIEWAVAILABLE(OBJ, MS) returns a logical vector containing an entry
        %  for each view that is defined.
        
        ret = obj.MaxRecommended>0;
        if nargin==3
            ret = ret(Index);
        end
        
        end  % isViewAvailable
        
        %----------------------------------------
        function N = numViews(obj)
        %NUMVIEWS Return the number of views that are listed
        %
        %  N = NUMVIEWS(OBJ) returns the number of views that have been defined in
        %  the ViewList object.
        
        N = length(obj.Labels);
        
        end  % numViews
        
    end  % public methods
    
    methods (Access=protected) % protected methods
        %----------------------------------------
        function pRemoveViewInstance(obj, ViewID)
        %PREMOVEVIEWINSTANCE Respond to a view object being deleted
        %
        %  PREMOVEVIEWINSTANCE(OBJ, VIEWID) decrements the count the number of
        %  views of type VIEWID and removes the listener on the view that has been
        %  deleted.
        
        Index = (obj.ViewID==ViewID);
        obj.NumCreated(Index) = obj.NumCreated(Index)-1;
        
        % Find listener that is attached to a view that is being destroyed, and
        % removed this from the list of listeners
        L = obj.DestructionListeners{Index};
        keep = true(size(L));
        for n = 1:length(L)
            if ~isvalid([L(n).Source{:}]) || mbcgui.util.isBeingDestroyed([L(n).Source{:}])
                keep(n) = false;
            end
        end
        L = L(keep);
        obj.DestructionListeners{Index} = L;
        
        end  % pRemoveViewInstance
        
    end % protected methods

    
end  % classdef

function val = i_checkcell(~, val)
if ~iscell(val) || (~isempty(val) && ~isvector(val))
    error(message('mbc:mbcmultiview:ViewList:InvalidPropertyValue'));
end
end  % i_checkcell

function val = i_checkvect(~, val)
if ~isnumeric(val) || (~isempty(val) && ~isvector(val))
    error(message('mbc:mbcmultiview:ViewList:InvalidPropertyValue1'));
end
end  % i_checkvect

function data = i_getcelldata(sView, field, defvalue, data)
if isfield(sView, field)
    data = [data, {sView.(field)}];
else
    data = [data, {defvalue}];
end
end  % i_getcelldata

function data = i_getnumdata(sView, field, defvalue, data)
if isfield(sView, field)
    data = [data, sView.(field)];
else
    data = [data, defvalue];
end
end  % i_getnumdata

function i_viewclosed(~, ~, obj, ViewID)
obj.pRemoveViewInstance(ViewID);
end  % i_viewclosed